xref: /titanic_51/usr/src/lib/libfsmgt/common/fs_mounts.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Traverses /etc/mnttab in order to find mounted file systems.
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate #include <errno.h>
33*7c478bd9Sstevel@tonic-gate #include <unistd.h>
34*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
35*7c478bd9Sstevel@tonic-gate #include <stdio.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
39*7c478bd9Sstevel@tonic-gate #include <strings.h>
40*7c478bd9Sstevel@tonic-gate #include "libfsmgt.h"
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate /*
43*7c478bd9Sstevel@tonic-gate  * Private variables
44*7c478bd9Sstevel@tonic-gate  */
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate /*
47*7c478bd9Sstevel@tonic-gate  * Private method declarations
48*7c478bd9Sstevel@tonic-gate  */
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate static fs_mntlist_t	*create_mntlist_entry(struct mnttab mnttab_entry);
51*7c478bd9Sstevel@tonic-gate static fs_mntlist_t	*create_extmntlist_entry(struct extmnttab mnttab_entry);
52*7c478bd9Sstevel@tonic-gate static struct mnttab	*create_mnttab_filter(char *resource, char *mountp,
53*7c478bd9Sstevel@tonic-gate 				char *fstype, char *mntopts, char *time);
54*7c478bd9Sstevel@tonic-gate static void		find_overlayed_filesystems(fs_mntlist_t *mnt_list,
55*7c478bd9Sstevel@tonic-gate 				boolean_t filtered_list, int *errp);
56*7c478bd9Sstevel@tonic-gate static void		free_mnttab_entry(struct mnttab *mnttab_entry);
57*7c478bd9Sstevel@tonic-gate static char		*is_option(char *opt_string, char *opt, int *errp);
58*7c478bd9Sstevel@tonic-gate boolean_t 		is_overlayed(fs_mntlist_t *complete_mnt_list,
59*7c478bd9Sstevel@tonic-gate 				char *mountp);
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate /*
63*7c478bd9Sstevel@tonic-gate  * Public methods
64*7c478bd9Sstevel@tonic-gate  */
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate void
67*7c478bd9Sstevel@tonic-gate fs_free_mount_list(fs_mntlist_t *headp) {
68*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*tmp;
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate 	while (headp != NULL) {
71*7c478bd9Sstevel@tonic-gate 		tmp = headp->next;
72*7c478bd9Sstevel@tonic-gate 		free(headp->resource);
73*7c478bd9Sstevel@tonic-gate 		free(headp->mountp);
74*7c478bd9Sstevel@tonic-gate 		free(headp->fstype);
75*7c478bd9Sstevel@tonic-gate 		free(headp->mntopts);
76*7c478bd9Sstevel@tonic-gate 		free(headp->time);
77*7c478bd9Sstevel@tonic-gate 		headp->next = NULL;
78*7c478bd9Sstevel@tonic-gate 		free(headp);
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate 		headp = tmp;
81*7c478bd9Sstevel@tonic-gate 	}
82*7c478bd9Sstevel@tonic-gate } /* fs_free_mount_list */
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate unsigned long long
85*7c478bd9Sstevel@tonic-gate fs_get_availablesize(char *mntpnt, int *errp) {
86*7c478bd9Sstevel@tonic-gate 	struct statvfs64	stvfs;
87*7c478bd9Sstevel@tonic-gate 	unsigned long long	availablesize;
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate 	*errp = 0;
90*7c478bd9Sstevel@tonic-gate 	if (mntpnt == NULL) {
91*7c478bd9Sstevel@tonic-gate 		/*
92*7c478bd9Sstevel@tonic-gate 		 * Set errp to invalid parameter - EINVAL
93*7c478bd9Sstevel@tonic-gate 		 */
94*7c478bd9Sstevel@tonic-gate 		*errp = EINVAL;
95*7c478bd9Sstevel@tonic-gate 		return (0);
96*7c478bd9Sstevel@tonic-gate 	}
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate 	if (statvfs64(mntpnt, &stvfs) != -1) {
99*7c478bd9Sstevel@tonic-gate 		availablesize = stvfs.f_bfree;
100*7c478bd9Sstevel@tonic-gate 		availablesize = availablesize * stvfs.f_frsize;
101*7c478bd9Sstevel@tonic-gate 	} else {
102*7c478bd9Sstevel@tonic-gate 		*errp = errno;
103*7c478bd9Sstevel@tonic-gate 		return (0);
104*7c478bd9Sstevel@tonic-gate 	}  /* if (statvfs64(mntpnt, &stvfs) != -1) */
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	return (availablesize);
107*7c478bd9Sstevel@tonic-gate } /* fs_get_availablesize */
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate unsigned long long
110*7c478bd9Sstevel@tonic-gate fs_get_avail_for_nonsuperuser_size(char *mntpnt, int *errp) {
111*7c478bd9Sstevel@tonic-gate 	struct statvfs64	stvfs;
112*7c478bd9Sstevel@tonic-gate 	unsigned long long	avail_for_nonsu_size;
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 	*errp = 0;
115*7c478bd9Sstevel@tonic-gate 	if (mntpnt == NULL) {
116*7c478bd9Sstevel@tonic-gate 		/*
117*7c478bd9Sstevel@tonic-gate 		 * Set errp to invalid parameter - EINVAL
118*7c478bd9Sstevel@tonic-gate 		 */
119*7c478bd9Sstevel@tonic-gate 		*errp = EINVAL;
120*7c478bd9Sstevel@tonic-gate 		return (0);
121*7c478bd9Sstevel@tonic-gate 	}
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate 	if (statvfs64(mntpnt, &stvfs) != -1) {
124*7c478bd9Sstevel@tonic-gate 		avail_for_nonsu_size = stvfs.f_bavail;
125*7c478bd9Sstevel@tonic-gate 		avail_for_nonsu_size = avail_for_nonsu_size * stvfs.f_frsize;
126*7c478bd9Sstevel@tonic-gate 	} else {
127*7c478bd9Sstevel@tonic-gate 		*errp = errno;
128*7c478bd9Sstevel@tonic-gate 		return (0);
129*7c478bd9Sstevel@tonic-gate 	} /* if (statvfs64(mntpnt, &stvfs) != -1) */
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 	return (avail_for_nonsu_size);
132*7c478bd9Sstevel@tonic-gate } /* fs_get_avail_for_nonsuperuser_size(char *mntpnt, int *errp) */
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate unsigned long long
135*7c478bd9Sstevel@tonic-gate fs_get_blocksize(char *mntpnt, int *errp) {
136*7c478bd9Sstevel@tonic-gate 	struct statvfs64	stvfs;
137*7c478bd9Sstevel@tonic-gate 	unsigned long long	blocksize;
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate 	*errp = 0;
140*7c478bd9Sstevel@tonic-gate 	if (mntpnt == NULL) {
141*7c478bd9Sstevel@tonic-gate 		/*
142*7c478bd9Sstevel@tonic-gate 		 * Set errp to invalid parameter - EINVAL
143*7c478bd9Sstevel@tonic-gate 		 */
144*7c478bd9Sstevel@tonic-gate 		*errp = EINVAL;
145*7c478bd9Sstevel@tonic-gate 		return (0);
146*7c478bd9Sstevel@tonic-gate 	}
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	if (statvfs64(mntpnt, &stvfs) != -1) {
149*7c478bd9Sstevel@tonic-gate 		blocksize = stvfs.f_bsize;
150*7c478bd9Sstevel@tonic-gate 	} else {
151*7c478bd9Sstevel@tonic-gate 		*errp = errno;
152*7c478bd9Sstevel@tonic-gate 		return (0);
153*7c478bd9Sstevel@tonic-gate 	} /* if (statvfs64(mntpnt, &stvfs) != -1) */
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate 	return (blocksize);
156*7c478bd9Sstevel@tonic-gate } /* fs_get_blocksize */
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate fs_mntlist_t *
159*7c478bd9Sstevel@tonic-gate fs_get_filtered_mount_list(char *resource, char *mountp, char *fstype,
160*7c478bd9Sstevel@tonic-gate 	char *mntopts, char *time, boolean_t find_overlays, int *errp) {
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*newp;
163*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*headp;
164*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*tailp;
165*7c478bd9Sstevel@tonic-gate 	FILE		*fp;
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	*errp = 0;
168*7c478bd9Sstevel@tonic-gate 	headp = NULL;
169*7c478bd9Sstevel@tonic-gate 	tailp = NULL;
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 	if ((fp = fopen(MNTTAB, "r")) != NULL) {
172*7c478bd9Sstevel@tonic-gate 		struct mnttab   mnttab_entry;
173*7c478bd9Sstevel@tonic-gate 		struct mnttab   *search_entry;
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 		search_entry = create_mnttab_filter(resource, mountp, fstype,
176*7c478bd9Sstevel@tonic-gate 			mntopts, time);
177*7c478bd9Sstevel@tonic-gate 		if (search_entry == NULL) {
178*7c478bd9Sstevel@tonic-gate 			/*
179*7c478bd9Sstevel@tonic-gate 			 * Out of memory
180*7c478bd9Sstevel@tonic-gate 			 */
181*7c478bd9Sstevel@tonic-gate 			fs_free_mount_list(headp);
182*7c478bd9Sstevel@tonic-gate 			(void) fclose(fp);
183*7c478bd9Sstevel@tonic-gate 			*errp = ENOMEM;
184*7c478bd9Sstevel@tonic-gate 			return (NULL);
185*7c478bd9Sstevel@tonic-gate 		}
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 		while (getmntany(fp, &mnttab_entry, search_entry) == 0) {
188*7c478bd9Sstevel@tonic-gate 			/* Add to list to be returned */
189*7c478bd9Sstevel@tonic-gate 			newp = create_mntlist_entry(mnttab_entry);
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 			if (newp == NULL) {
192*7c478bd9Sstevel@tonic-gate 				/*
193*7c478bd9Sstevel@tonic-gate 				 * Out of memory
194*7c478bd9Sstevel@tonic-gate 				 */
195*7c478bd9Sstevel@tonic-gate 				fs_free_mount_list(headp);
196*7c478bd9Sstevel@tonic-gate 				(void) fclose(fp);
197*7c478bd9Sstevel@tonic-gate 				*errp = ENOMEM;
198*7c478bd9Sstevel@tonic-gate 				return (NULL);
199*7c478bd9Sstevel@tonic-gate 			}
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 			if (headp == NULL) {
202*7c478bd9Sstevel@tonic-gate 				headp = newp;
203*7c478bd9Sstevel@tonic-gate 				tailp = newp;
204*7c478bd9Sstevel@tonic-gate 			} else {
205*7c478bd9Sstevel@tonic-gate 				tailp->next = newp;
206*7c478bd9Sstevel@tonic-gate 				tailp = newp;
207*7c478bd9Sstevel@tonic-gate 			}
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 		}
210*7c478bd9Sstevel@tonic-gate 		free_mnttab_entry(search_entry);
211*7c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
212*7c478bd9Sstevel@tonic-gate 		if (find_overlays == B_TRUE)
213*7c478bd9Sstevel@tonic-gate 			find_overlayed_filesystems(headp, B_TRUE, errp);
214*7c478bd9Sstevel@tonic-gate 	} else {
215*7c478bd9Sstevel@tonic-gate 		*errp = errno;
216*7c478bd9Sstevel@tonic-gate 	} /* if ((fp = fopen(MNTTAB, "r")) != NULL) */
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate 	return (headp);
219*7c478bd9Sstevel@tonic-gate } /* fs_get_filtered_mount_list */
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate unsigned long
222*7c478bd9Sstevel@tonic-gate fs_get_fragsize(char *mntpnt, int *errp) {
223*7c478bd9Sstevel@tonic-gate 	struct statvfs64	stvfs;
224*7c478bd9Sstevel@tonic-gate 	unsigned long		fragsize;
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 	*errp = 0;
227*7c478bd9Sstevel@tonic-gate 	if (mntpnt == NULL) {
228*7c478bd9Sstevel@tonic-gate 		/*
229*7c478bd9Sstevel@tonic-gate 		 * Set errp to invalid parameter - EINVAL
230*7c478bd9Sstevel@tonic-gate 		 */
231*7c478bd9Sstevel@tonic-gate 		*errp = EINVAL;
232*7c478bd9Sstevel@tonic-gate 		return (0);
233*7c478bd9Sstevel@tonic-gate 	}
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	if (statvfs64(mntpnt, &stvfs) != -1) {
236*7c478bd9Sstevel@tonic-gate 		fragsize = stvfs.f_frsize;
237*7c478bd9Sstevel@tonic-gate 	} else {
238*7c478bd9Sstevel@tonic-gate 		*errp = errno;
239*7c478bd9Sstevel@tonic-gate 		return (0);
240*7c478bd9Sstevel@tonic-gate 	} /* (statvfs64(mntpnt, &stvfs) != -1) */
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	return (fragsize);
243*7c478bd9Sstevel@tonic-gate } /* fs_get_fragsize(char *mntpnt, int *errp) */
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate unsigned long
246*7c478bd9Sstevel@tonic-gate fs_get_maxfilenamelen(char *mntpnt, int *errp) {
247*7c478bd9Sstevel@tonic-gate 	long int		returned_val;
248*7c478bd9Sstevel@tonic-gate 	unsigned long		maxfilenamelen;
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	*errp = 0;
251*7c478bd9Sstevel@tonic-gate 	if (mntpnt == NULL) {
252*7c478bd9Sstevel@tonic-gate 		/*
253*7c478bd9Sstevel@tonic-gate 		 * Set errp to invalid parameter - EINVAL
254*7c478bd9Sstevel@tonic-gate 		 */
255*7c478bd9Sstevel@tonic-gate 		*errp = EINVAL;
256*7c478bd9Sstevel@tonic-gate 		return (0);
257*7c478bd9Sstevel@tonic-gate 	}
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 	returned_val = pathconf(mntpnt, _PC_PATH_MAX);
260*7c478bd9Sstevel@tonic-gate 	if (returned_val != -1) {
261*7c478bd9Sstevel@tonic-gate 		maxfilenamelen = (unsigned long)returned_val;
262*7c478bd9Sstevel@tonic-gate 	} else {
263*7c478bd9Sstevel@tonic-gate 		*errp = errno;
264*7c478bd9Sstevel@tonic-gate 		return (0);
265*7c478bd9Sstevel@tonic-gate 	}
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 	return (maxfilenamelen);
268*7c478bd9Sstevel@tonic-gate } /* fs_get_maxfilenamelen */
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate fs_mntlist_t *
271*7c478bd9Sstevel@tonic-gate fs_get_mounts_by_mntopt(char *mntopt, boolean_t find_overlays, int *errp) {
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*newp;
274*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*headp;
275*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*tailp;
276*7c478bd9Sstevel@tonic-gate 	FILE		*fp;
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	*errp = 0;
279*7c478bd9Sstevel@tonic-gate 	headp = NULL;
280*7c478bd9Sstevel@tonic-gate 	tailp = NULL;
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 	if (mntopt == NULL)
283*7c478bd9Sstevel@tonic-gate 		return (NULL);
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 	if ((fp = fopen(MNTTAB, "r")) != NULL) {
286*7c478bd9Sstevel@tonic-gate 		struct mnttab mnttab_entry;
287*7c478bd9Sstevel@tonic-gate 		char *opt_found;
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 		while (getmntent(fp, &mnttab_entry) == 0) {
290*7c478bd9Sstevel@tonic-gate 			opt_found = hasmntopt(&mnttab_entry, mntopt);
291*7c478bd9Sstevel@tonic-gate 			if (opt_found != NULL) {
292*7c478bd9Sstevel@tonic-gate 				/*
293*7c478bd9Sstevel@tonic-gate 				 * Add to list to be returned
294*7c478bd9Sstevel@tonic-gate 				 */
295*7c478bd9Sstevel@tonic-gate 				newp = create_mntlist_entry(mnttab_entry);
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 				if (newp == NULL) {
298*7c478bd9Sstevel@tonic-gate 					/*
299*7c478bd9Sstevel@tonic-gate 					 * Out of memory
300*7c478bd9Sstevel@tonic-gate 					 */
301*7c478bd9Sstevel@tonic-gate 					fs_free_mount_list(headp);
302*7c478bd9Sstevel@tonic-gate 					(void) fclose(fp);
303*7c478bd9Sstevel@tonic-gate 					*errp = ENOMEM;
304*7c478bd9Sstevel@tonic-gate 					return (NULL);
305*7c478bd9Sstevel@tonic-gate 				}
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 				if (headp == NULL) {
308*7c478bd9Sstevel@tonic-gate 					headp = newp;
309*7c478bd9Sstevel@tonic-gate 					tailp = newp;
310*7c478bd9Sstevel@tonic-gate 				} else {
311*7c478bd9Sstevel@tonic-gate 					tailp->next = newp;
312*7c478bd9Sstevel@tonic-gate 					tailp = newp;
313*7c478bd9Sstevel@tonic-gate 				}
314*7c478bd9Sstevel@tonic-gate 			} /* if (char != NULL) */
315*7c478bd9Sstevel@tonic-gate 		}
316*7c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
317*7c478bd9Sstevel@tonic-gate 		if (find_overlays == B_TRUE)
318*7c478bd9Sstevel@tonic-gate 			find_overlayed_filesystems(headp, B_TRUE, errp);
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 	} else {
321*7c478bd9Sstevel@tonic-gate 		*errp = errno;
322*7c478bd9Sstevel@tonic-gate 	} /* if ((fp = fopen(MNTTAB, "r")) != NULL) */
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 	return (headp);
325*7c478bd9Sstevel@tonic-gate } /* fs_get_mounts_by_mntpnt */
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate fs_mntlist_t *
328*7c478bd9Sstevel@tonic-gate fs_get_mount_list(boolean_t find_overlays, int *errp) {
329*7c478bd9Sstevel@tonic-gate 	FILE 		*fp;
330*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*headp;
331*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*tailp;
332*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*newp;
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	*errp = 0;
335*7c478bd9Sstevel@tonic-gate 	headp = NULL;
336*7c478bd9Sstevel@tonic-gate 	tailp = NULL;
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	if ((fp = fopen(MNTTAB, "r")) != NULL) {
339*7c478bd9Sstevel@tonic-gate 		struct extmnttab	mnttab_entry;
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 		resetmnttab(fp);
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 		/*
344*7c478bd9Sstevel@tonic-gate 		 * getextmntent() Is used here so that we can use mnt_major
345*7c478bd9Sstevel@tonic-gate 		 * and mnt_minor to get the fsid. The fsid is used when
346*7c478bd9Sstevel@tonic-gate 		 * getting mount information from kstat.
347*7c478bd9Sstevel@tonic-gate 		 */
348*7c478bd9Sstevel@tonic-gate 		while (getextmntent(fp, &mnttab_entry,
349*7c478bd9Sstevel@tonic-gate 		    sizeof (struct extmnttab)) == 0) {
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 			newp = create_extmntlist_entry(mnttab_entry);
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 			if (newp == NULL) {
354*7c478bd9Sstevel@tonic-gate 				/*
355*7c478bd9Sstevel@tonic-gate 				 * Out of memory
356*7c478bd9Sstevel@tonic-gate 				 */
357*7c478bd9Sstevel@tonic-gate 				fs_free_mount_list(headp);
358*7c478bd9Sstevel@tonic-gate 				(void) fclose(fp);
359*7c478bd9Sstevel@tonic-gate 				*errp = ENOMEM;
360*7c478bd9Sstevel@tonic-gate 				return (NULL);
361*7c478bd9Sstevel@tonic-gate 			}
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 			if (headp == NULL) {
364*7c478bd9Sstevel@tonic-gate 				headp = newp;
365*7c478bd9Sstevel@tonic-gate 				tailp = newp;
366*7c478bd9Sstevel@tonic-gate 			} else {
367*7c478bd9Sstevel@tonic-gate 				tailp->next = newp;
368*7c478bd9Sstevel@tonic-gate 				tailp = newp;
369*7c478bd9Sstevel@tonic-gate 			}
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 		} /* while (getmntent(fp, &mnttab_entry) == 0) */
372*7c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
373*7c478bd9Sstevel@tonic-gate 		if (find_overlays)
374*7c478bd9Sstevel@tonic-gate 			find_overlayed_filesystems(headp, B_FALSE, errp);
375*7c478bd9Sstevel@tonic-gate 	} else {
376*7c478bd9Sstevel@tonic-gate 		*errp = errno;
377*7c478bd9Sstevel@tonic-gate 	} /* if ((fp = fopen(MNTTAB, "r")) != NULL) */
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 	/*
380*7c478bd9Sstevel@tonic-gate 	 * Caller must free the mount list
381*7c478bd9Sstevel@tonic-gate 	 */
382*7c478bd9Sstevel@tonic-gate 	return (headp);
383*7c478bd9Sstevel@tonic-gate } /* fs_get_mount_list */
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate boolean_t
386*7c478bd9Sstevel@tonic-gate fs_is_readonly(char *mntpnt, int *errp) {
387*7c478bd9Sstevel@tonic-gate 	struct statvfs64	stvfs;
388*7c478bd9Sstevel@tonic-gate 	boolean_t		readonly;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	*errp = 0;
391*7c478bd9Sstevel@tonic-gate 	if (mntpnt == NULL) {
392*7c478bd9Sstevel@tonic-gate 		/*
393*7c478bd9Sstevel@tonic-gate 		 * Set errp to invalid parameter - EINVAL
394*7c478bd9Sstevel@tonic-gate 		 */
395*7c478bd9Sstevel@tonic-gate 		*errp = EINVAL;
396*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
397*7c478bd9Sstevel@tonic-gate 	}
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 	if (statvfs64(mntpnt, &stvfs) != -1) {
400*7c478bd9Sstevel@tonic-gate 		readonly = stvfs.f_flag & ST_RDONLY;
401*7c478bd9Sstevel@tonic-gate 	} else {
402*7c478bd9Sstevel@tonic-gate 		*errp = errno;
403*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
404*7c478bd9Sstevel@tonic-gate 	}
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 	return (readonly);
407*7c478bd9Sstevel@tonic-gate } /* fs_is_readonly */
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate /*
410*7c478bd9Sstevel@tonic-gate  * This method will parse the given comma delimited option list (optlist) for
411*7c478bd9Sstevel@tonic-gate  * the option passed into the function.  If the option (opt) to search for
412*7c478bd9Sstevel@tonic-gate  * is one that sets a value such as onerror=, the value to the right of the "="
413*7c478bd9Sstevel@tonic-gate  * character will be returned from the function.  This function expects the
414*7c478bd9Sstevel@tonic-gate  * opt parameter to have the "=" character appended when searching for options
415*7c478bd9Sstevel@tonic-gate  * which set a value.
416*7c478bd9Sstevel@tonic-gate  *
417*7c478bd9Sstevel@tonic-gate  * If the option is found in the given optlist, the function will return the
418*7c478bd9Sstevel@tonic-gate  * option as found in the option list.
419*7c478bd9Sstevel@tonic-gate  * If the option is not found in the given optlist, the function will return
420*7c478bd9Sstevel@tonic-gate  * NULL.
421*7c478bd9Sstevel@tonic-gate  * If an error occurs, the function will return NULL and the errp will
422*7c478bd9Sstevel@tonic-gate  * reflect the error that has occurred.
423*7c478bd9Sstevel@tonic-gate  *
424*7c478bd9Sstevel@tonic-gate  * NOTE: The caller must free the space allocated for the return value by using
425*7c478bd9Sstevel@tonic-gate  * free().
426*7c478bd9Sstevel@tonic-gate  */
427*7c478bd9Sstevel@tonic-gate char *
428*7c478bd9Sstevel@tonic-gate fs_parse_optlist_for_option(char *optlist, char *opt, int *errp) {
429*7c478bd9Sstevel@tonic-gate 	const char	*delimiter = ",";
430*7c478bd9Sstevel@tonic-gate 	char		*token;
431*7c478bd9Sstevel@tonic-gate 	char		*return_value;
432*7c478bd9Sstevel@tonic-gate 	char		*optlist_copy;
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 	*errp = 0;
435*7c478bd9Sstevel@tonic-gate 	optlist_copy = strdup(optlist);
436*7c478bd9Sstevel@tonic-gate 	if (optlist_copy == NULL) {
437*7c478bd9Sstevel@tonic-gate 		*errp = errno;
438*7c478bd9Sstevel@tonic-gate 		return (NULL);
439*7c478bd9Sstevel@tonic-gate 	}
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 	token = strtok(optlist_copy, delimiter);
442*7c478bd9Sstevel@tonic-gate 	/*
443*7c478bd9Sstevel@tonic-gate 	 * Check to see if we have found the option.
444*7c478bd9Sstevel@tonic-gate 	 */
445*7c478bd9Sstevel@tonic-gate 	if (token == NULL) {
446*7c478bd9Sstevel@tonic-gate 		free(optlist_copy);
447*7c478bd9Sstevel@tonic-gate 		return (NULL);
448*7c478bd9Sstevel@tonic-gate 	} else if ((return_value = is_option(token, opt, errp)) != NULL) {
449*7c478bd9Sstevel@tonic-gate 		free(optlist_copy);
450*7c478bd9Sstevel@tonic-gate 		return (return_value);
451*7c478bd9Sstevel@tonic-gate 	}
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 	while (token != NULL) {
454*7c478bd9Sstevel@tonic-gate 		token = NULL;
455*7c478bd9Sstevel@tonic-gate 		token = strtok(NULL, delimiter);
456*7c478bd9Sstevel@tonic-gate 		/*
457*7c478bd9Sstevel@tonic-gate 		 * If token is NULL then then we are at the end of the list
458*7c478bd9Sstevel@tonic-gate 		 * and we can return NULL because the option was never found in
459*7c478bd9Sstevel@tonic-gate 		 * the option list.
460*7c478bd9Sstevel@tonic-gate 		 */
461*7c478bd9Sstevel@tonic-gate 		if (token == NULL) {
462*7c478bd9Sstevel@tonic-gate 			free(optlist_copy);
463*7c478bd9Sstevel@tonic-gate 			return (NULL);
464*7c478bd9Sstevel@tonic-gate 		} else if ((return_value =
465*7c478bd9Sstevel@tonic-gate 			is_option(token, opt, errp)) != NULL) {
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 			free(optlist_copy);
468*7c478bd9Sstevel@tonic-gate 			return (return_value);
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate 		}
471*7c478bd9Sstevel@tonic-gate 	}
472*7c478bd9Sstevel@tonic-gate 	free(optlist_copy);
473*7c478bd9Sstevel@tonic-gate 	return (NULL);
474*7c478bd9Sstevel@tonic-gate }
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate unsigned long long
477*7c478bd9Sstevel@tonic-gate fs_get_totalsize(char *mntpnt, int *errp) {
478*7c478bd9Sstevel@tonic-gate 	struct statvfs64	stvfs;
479*7c478bd9Sstevel@tonic-gate 	unsigned long long 	totalsize;
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 	*errp = 0;
482*7c478bd9Sstevel@tonic-gate 	if (mntpnt == NULL) {
483*7c478bd9Sstevel@tonic-gate 		/*
484*7c478bd9Sstevel@tonic-gate 		 * Set errp to invalid parameter - EINVAL
485*7c478bd9Sstevel@tonic-gate 		 */
486*7c478bd9Sstevel@tonic-gate 		*errp = EINVAL;
487*7c478bd9Sstevel@tonic-gate 		return (0);
488*7c478bd9Sstevel@tonic-gate 	}
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 	if (statvfs64(mntpnt, &stvfs) != -1) {
491*7c478bd9Sstevel@tonic-gate 		totalsize = stvfs.f_blocks;
492*7c478bd9Sstevel@tonic-gate 		totalsize = totalsize * stvfs.f_frsize;
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 	} else {
495*7c478bd9Sstevel@tonic-gate 		*errp = errno;
496*7c478bd9Sstevel@tonic-gate 		return (0);
497*7c478bd9Sstevel@tonic-gate 	} /* if (statvfs64(mntpnt, &stvfs) != -1) */
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 	return (totalsize);
500*7c478bd9Sstevel@tonic-gate } /* fs_get_totalsize */
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate unsigned long long
503*7c478bd9Sstevel@tonic-gate fs_get_usedsize(char *mntpnt, int *errp) {
504*7c478bd9Sstevel@tonic-gate 	struct statvfs64	stvfs;
505*7c478bd9Sstevel@tonic-gate 	unsigned long long	usedsize;
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	*errp = 0;
508*7c478bd9Sstevel@tonic-gate 	if (mntpnt == NULL) {
509*7c478bd9Sstevel@tonic-gate 		/*
510*7c478bd9Sstevel@tonic-gate 		 * Set errp to invalid parameter - EINVAL
511*7c478bd9Sstevel@tonic-gate 		 */
512*7c478bd9Sstevel@tonic-gate 		*errp = EINVAL;
513*7c478bd9Sstevel@tonic-gate 		return (0);
514*7c478bd9Sstevel@tonic-gate 	}
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 	if (statvfs64(mntpnt, &stvfs) != -1) {
517*7c478bd9Sstevel@tonic-gate 		usedsize = stvfs.f_blocks - stvfs.f_bfree;
518*7c478bd9Sstevel@tonic-gate 		usedsize = usedsize * stvfs.f_frsize;
519*7c478bd9Sstevel@tonic-gate 	} else {
520*7c478bd9Sstevel@tonic-gate 		*errp = errno;
521*7c478bd9Sstevel@tonic-gate 		return (0);
522*7c478bd9Sstevel@tonic-gate 	} /* if (statvfs64(mntpnt, &stvfs) != -1) */
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate 	return (usedsize);
525*7c478bd9Sstevel@tonic-gate } /* fs_get_usedsize */
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate /*
528*7c478bd9Sstevel@tonic-gate  * Private methods
529*7c478bd9Sstevel@tonic-gate  */
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate static fs_mntlist_t *
532*7c478bd9Sstevel@tonic-gate create_mntlist_entry(struct mnttab mnttab_entry) {
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*newp;
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate 	newp = (fs_mntlist_t *)calloc((size_t)1,
537*7c478bd9Sstevel@tonic-gate 		(size_t)sizeof (fs_mntlist_t));
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate 	if (newp == NULL) {
540*7c478bd9Sstevel@tonic-gate 		/*
541*7c478bd9Sstevel@tonic-gate 		 * Out of memory
542*7c478bd9Sstevel@tonic-gate 		 */
543*7c478bd9Sstevel@tonic-gate 		return (NULL);
544*7c478bd9Sstevel@tonic-gate 	}
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 	newp->resource = strdup(mnttab_entry.mnt_special);
547*7c478bd9Sstevel@tonic-gate 	if (newp->resource == NULL) {
548*7c478bd9Sstevel@tonic-gate 		/*
549*7c478bd9Sstevel@tonic-gate 		 *  Out of memory
550*7c478bd9Sstevel@tonic-gate 		 */
551*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(newp);
552*7c478bd9Sstevel@tonic-gate 		return (NULL);
553*7c478bd9Sstevel@tonic-gate 	}
554*7c478bd9Sstevel@tonic-gate 	newp->mountp = strdup(mnttab_entry.mnt_mountp);
555*7c478bd9Sstevel@tonic-gate 	if (newp->mountp == NULL) {
556*7c478bd9Sstevel@tonic-gate 		/*
557*7c478bd9Sstevel@tonic-gate 		 * Out of memory
558*7c478bd9Sstevel@tonic-gate 		 */
559*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(newp);
560*7c478bd9Sstevel@tonic-gate 		return (NULL);
561*7c478bd9Sstevel@tonic-gate 	}
562*7c478bd9Sstevel@tonic-gate 	newp->fstype = strdup(mnttab_entry.mnt_fstype);
563*7c478bd9Sstevel@tonic-gate 	if (newp->fstype == NULL) {
564*7c478bd9Sstevel@tonic-gate 		/*
565*7c478bd9Sstevel@tonic-gate 		 *  Out of memory
566*7c478bd9Sstevel@tonic-gate 		 */
567*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(newp);
568*7c478bd9Sstevel@tonic-gate 		return (NULL);
569*7c478bd9Sstevel@tonic-gate 	}
570*7c478bd9Sstevel@tonic-gate 	newp->mntopts = strdup(mnttab_entry.mnt_mntopts);
571*7c478bd9Sstevel@tonic-gate 	if (newp->mntopts == NULL) {
572*7c478bd9Sstevel@tonic-gate 		/*
573*7c478bd9Sstevel@tonic-gate 		 * Out of memory
574*7c478bd9Sstevel@tonic-gate 		 */
575*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(newp);
576*7c478bd9Sstevel@tonic-gate 		return (NULL);
577*7c478bd9Sstevel@tonic-gate 	}
578*7c478bd9Sstevel@tonic-gate 	newp->time = strdup(mnttab_entry.mnt_time);
579*7c478bd9Sstevel@tonic-gate 	if (newp->time == NULL) {
580*7c478bd9Sstevel@tonic-gate 		/*
581*7c478bd9Sstevel@tonic-gate 		 * Out of memory
582*7c478bd9Sstevel@tonic-gate 		 */
583*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(newp);
584*7c478bd9Sstevel@tonic-gate 		return (NULL);
585*7c478bd9Sstevel@tonic-gate 	}
586*7c478bd9Sstevel@tonic-gate 	newp->next = NULL;
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	return (newp);
589*7c478bd9Sstevel@tonic-gate } /* create_mntlist_entry */
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate static fs_mntlist_t *
592*7c478bd9Sstevel@tonic-gate create_extmntlist_entry(struct extmnttab mnttab_entry) {
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t	*newp;
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 	newp = (fs_mntlist_t *)calloc((size_t)1,
597*7c478bd9Sstevel@tonic-gate 		(size_t)sizeof (fs_mntlist_t));
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate 	if (newp == NULL) {
600*7c478bd9Sstevel@tonic-gate 		/*
601*7c478bd9Sstevel@tonic-gate 		 * Out of memory
602*7c478bd9Sstevel@tonic-gate 		 */
603*7c478bd9Sstevel@tonic-gate 		return (NULL);
604*7c478bd9Sstevel@tonic-gate 	}
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 	newp->resource = strdup(mnttab_entry.mnt_special);
607*7c478bd9Sstevel@tonic-gate 	if (newp->resource == NULL) {
608*7c478bd9Sstevel@tonic-gate 		/*
609*7c478bd9Sstevel@tonic-gate 		 *  Out of memory
610*7c478bd9Sstevel@tonic-gate 		 */
611*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(newp);
612*7c478bd9Sstevel@tonic-gate 		return (NULL);
613*7c478bd9Sstevel@tonic-gate 	}
614*7c478bd9Sstevel@tonic-gate 	newp->mountp = strdup(mnttab_entry.mnt_mountp);
615*7c478bd9Sstevel@tonic-gate 	if (newp->mountp == NULL) {
616*7c478bd9Sstevel@tonic-gate 		/*
617*7c478bd9Sstevel@tonic-gate 		 * Out of memory
618*7c478bd9Sstevel@tonic-gate 		 */
619*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(newp);
620*7c478bd9Sstevel@tonic-gate 		return (NULL);
621*7c478bd9Sstevel@tonic-gate 	}
622*7c478bd9Sstevel@tonic-gate 	newp->fstype = strdup(mnttab_entry.mnt_fstype);
623*7c478bd9Sstevel@tonic-gate 	if (newp->fstype == NULL) {
624*7c478bd9Sstevel@tonic-gate 		/*
625*7c478bd9Sstevel@tonic-gate 		 *  Out of memory
626*7c478bd9Sstevel@tonic-gate 		 */
627*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(newp);
628*7c478bd9Sstevel@tonic-gate 		return (NULL);
629*7c478bd9Sstevel@tonic-gate 	}
630*7c478bd9Sstevel@tonic-gate 	newp->mntopts = strdup(mnttab_entry.mnt_mntopts);
631*7c478bd9Sstevel@tonic-gate 	if (newp->mntopts == NULL) {
632*7c478bd9Sstevel@tonic-gate 		/*
633*7c478bd9Sstevel@tonic-gate 		 * Out of memory
634*7c478bd9Sstevel@tonic-gate 		 */
635*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(newp);
636*7c478bd9Sstevel@tonic-gate 		return (NULL);
637*7c478bd9Sstevel@tonic-gate 	}
638*7c478bd9Sstevel@tonic-gate 	newp->time = strdup(mnttab_entry.mnt_time);
639*7c478bd9Sstevel@tonic-gate 	if (newp->time == NULL) {
640*7c478bd9Sstevel@tonic-gate 		/*
641*7c478bd9Sstevel@tonic-gate 		 * Out of memory
642*7c478bd9Sstevel@tonic-gate 		 */
643*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(newp);
644*7c478bd9Sstevel@tonic-gate 		return (NULL);
645*7c478bd9Sstevel@tonic-gate 	}
646*7c478bd9Sstevel@tonic-gate 	newp->major = mnttab_entry.mnt_major;
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 	newp->minor = mnttab_entry.mnt_minor;
649*7c478bd9Sstevel@tonic-gate 
650*7c478bd9Sstevel@tonic-gate 	newp->next = NULL;
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	return (newp);
653*7c478bd9Sstevel@tonic-gate } /* create_extmntlist_entry */
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate static struct mnttab *
656*7c478bd9Sstevel@tonic-gate create_mnttab_filter(char *resource, char *mountp, char *fstype, char *mntopts,
657*7c478bd9Sstevel@tonic-gate 	char *time) {
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	struct mnttab	*search_entry;
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	search_entry = (struct mnttab *)calloc((size_t)1,
662*7c478bd9Sstevel@tonic-gate 		(size_t)sizeof (struct mnttab));
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate 	if (search_entry == NULL) {
665*7c478bd9Sstevel@tonic-gate 		/*
666*7c478bd9Sstevel@tonic-gate 		 * Out of memory
667*7c478bd9Sstevel@tonic-gate 		 */
668*7c478bd9Sstevel@tonic-gate 		return (NULL);
669*7c478bd9Sstevel@tonic-gate 	}
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	if (resource != NULL) {
672*7c478bd9Sstevel@tonic-gate 		search_entry->mnt_special = strdup(resource);
673*7c478bd9Sstevel@tonic-gate 		if (search_entry->mnt_special == NULL) {
674*7c478bd9Sstevel@tonic-gate 			/*
675*7c478bd9Sstevel@tonic-gate 			 * Out of memory
676*7c478bd9Sstevel@tonic-gate 			 */
677*7c478bd9Sstevel@tonic-gate 			free_mnttab_entry(search_entry);
678*7c478bd9Sstevel@tonic-gate 			return (NULL);
679*7c478bd9Sstevel@tonic-gate 		}
680*7c478bd9Sstevel@tonic-gate 	}
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate 	if (mountp != NULL) {
683*7c478bd9Sstevel@tonic-gate 		search_entry->mnt_mountp = strdup(mountp);
684*7c478bd9Sstevel@tonic-gate 		if (search_entry->mnt_mountp == NULL) {
685*7c478bd9Sstevel@tonic-gate 			/*
686*7c478bd9Sstevel@tonic-gate 			 * Out of memory
687*7c478bd9Sstevel@tonic-gate 			 */
688*7c478bd9Sstevel@tonic-gate 			free_mnttab_entry(search_entry);
689*7c478bd9Sstevel@tonic-gate 			return (NULL);
690*7c478bd9Sstevel@tonic-gate 		}
691*7c478bd9Sstevel@tonic-gate 	}
692*7c478bd9Sstevel@tonic-gate 
693*7c478bd9Sstevel@tonic-gate 	if (fstype != NULL) {
694*7c478bd9Sstevel@tonic-gate 		search_entry->mnt_fstype = strdup(fstype);
695*7c478bd9Sstevel@tonic-gate 		if (search_entry->mnt_fstype == NULL) {
696*7c478bd9Sstevel@tonic-gate 			/*
697*7c478bd9Sstevel@tonic-gate 			 * Out of memory
698*7c478bd9Sstevel@tonic-gate 			 */
699*7c478bd9Sstevel@tonic-gate 			free_mnttab_entry(search_entry);
700*7c478bd9Sstevel@tonic-gate 			return (NULL);
701*7c478bd9Sstevel@tonic-gate 		}
702*7c478bd9Sstevel@tonic-gate 	}
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 	if (mntopts != NULL) {
705*7c478bd9Sstevel@tonic-gate 		search_entry->mnt_mntopts = strdup(mntopts);
706*7c478bd9Sstevel@tonic-gate 		if (search_entry->mnt_mntopts == NULL) {
707*7c478bd9Sstevel@tonic-gate 			/*
708*7c478bd9Sstevel@tonic-gate 			 * Out of memory
709*7c478bd9Sstevel@tonic-gate 			 */
710*7c478bd9Sstevel@tonic-gate 			free_mnttab_entry(search_entry);
711*7c478bd9Sstevel@tonic-gate 			return (NULL);
712*7c478bd9Sstevel@tonic-gate 		}
713*7c478bd9Sstevel@tonic-gate 	}
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate 	if (time != NULL) {
716*7c478bd9Sstevel@tonic-gate 		search_entry->mnt_time = strdup(time);
717*7c478bd9Sstevel@tonic-gate 		if (search_entry->mnt_time == NULL) {
718*7c478bd9Sstevel@tonic-gate 			/*
719*7c478bd9Sstevel@tonic-gate 			 * Out of memory
720*7c478bd9Sstevel@tonic-gate 			 */
721*7c478bd9Sstevel@tonic-gate 			free_mnttab_entry(search_entry);
722*7c478bd9Sstevel@tonic-gate 			return (NULL);
723*7c478bd9Sstevel@tonic-gate 		}
724*7c478bd9Sstevel@tonic-gate 	}
725*7c478bd9Sstevel@tonic-gate 
726*7c478bd9Sstevel@tonic-gate 	return (search_entry);
727*7c478bd9Sstevel@tonic-gate } /* create_mnttab_filter */
728*7c478bd9Sstevel@tonic-gate 
729*7c478bd9Sstevel@tonic-gate /*
730*7c478bd9Sstevel@tonic-gate  * We will go through the /etc/mnttab entries to determine the
731*7c478bd9Sstevel@tonic-gate  * instances of overlayed file systems.  We do this with the following
732*7c478bd9Sstevel@tonic-gate  * assumptions:
733*7c478bd9Sstevel@tonic-gate  *
734*7c478bd9Sstevel@tonic-gate  * 1.) Entries in mnttab are ordered in the way that the most recent
735*7c478bd9Sstevel@tonic-gate  * mounts are placed at the bottom of /etc/mnttab.  Contract to be
736*7c478bd9Sstevel@tonic-gate  * filed:
737*7c478bd9Sstevel@tonic-gate  * 2.) Mnttab entries that are returned from all mnttab library
738*7c478bd9Sstevel@tonic-gate  * functions such as getmntent, getextmntent, and getmntany in the order
739*7c478bd9Sstevel@tonic-gate  * as they are found in /etc/mnttab.  Goes along with assumption #1.
740*7c478bd9Sstevel@tonic-gate  * 3.) All automounted NFS file systems will have an autofs entry and
741*7c478bd9Sstevel@tonic-gate  * a NFS entry in /etc/mnttab with the same mount point.  Autofs
742*7c478bd9Sstevel@tonic-gate  * entries can be ignored.
743*7c478bd9Sstevel@tonic-gate  * 4.) The device id (dev=) uniquely identifies a mounted file system
744*7c478bd9Sstevel@tonic-gate  * on a host.
745*7c478bd9Sstevel@tonic-gate  *
746*7c478bd9Sstevel@tonic-gate  * Algorithm explanation:
747*7c478bd9Sstevel@tonic-gate  * ----------------------
748*7c478bd9Sstevel@tonic-gate  * For each mnt_list entry
749*7c478bd9Sstevel@tonic-gate  * 1.) Compare it to each /etc/mnttab entry starting at the point in mnttab
750*7c478bd9Sstevel@tonic-gate  * where the mnt_list entry mount is and look for matching mount points,
751*7c478bd9Sstevel@tonic-gate  * but ignore all "autofs" entries
752*7c478bd9Sstevel@tonic-gate  *      If a two entries are found with the same mount point mark the mnt_list
753*7c478bd9Sstevel@tonic-gate  *	entry as being overlayed.
754*7c478bd9Sstevel@tonic-gate  */
755*7c478bd9Sstevel@tonic-gate static void
756*7c478bd9Sstevel@tonic-gate find_overlayed_filesystems(fs_mntlist_t *mnt_list,
757*7c478bd9Sstevel@tonic-gate 	boolean_t filtered_list, int *errp) {
758*7c478bd9Sstevel@tonic-gate 
759*7c478bd9Sstevel@tonic-gate 	boolean_t exit = B_FALSE;
760*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t *mnt_list_to_compare;
761*7c478bd9Sstevel@tonic-gate 	fs_mntlist_t *tmp;
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate 	*errp = 0;
764*7c478bd9Sstevel@tonic-gate 	if (filtered_list == B_TRUE) {
765*7c478bd9Sstevel@tonic-gate 		/*
766*7c478bd9Sstevel@tonic-gate 		 * Get the complete mount list
767*7c478bd9Sstevel@tonic-gate 		 */
768*7c478bd9Sstevel@tonic-gate 		mnt_list_to_compare = fs_get_mount_list(B_FALSE, errp);
769*7c478bd9Sstevel@tonic-gate 		if (mnt_list_to_compare == NULL) {
770*7c478bd9Sstevel@tonic-gate 			/*
771*7c478bd9Sstevel@tonic-gate 			 * If complete_mnt_list is NULL there are two
772*7c478bd9Sstevel@tonic-gate 			 * possibilites:
773*7c478bd9Sstevel@tonic-gate 			 * 1.) There are simply no entries in /etc/mnttab.
774*7c478bd9Sstevel@tonic-gate 			 * 2.) An error was encountered.  errp will reflect
775*7c478bd9Sstevel@tonic-gate 			 * the error.
776*7c478bd9Sstevel@tonic-gate 			 */
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 			return;
779*7c478bd9Sstevel@tonic-gate 		}
780*7c478bd9Sstevel@tonic-gate 	} else {
781*7c478bd9Sstevel@tonic-gate 		mnt_list_to_compare = mnt_list;
782*7c478bd9Sstevel@tonic-gate 	}
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate 	tmp = mnt_list_to_compare;
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate 	while (mnt_list != NULL) {
787*7c478bd9Sstevel@tonic-gate 		if (!(strcmp(mnt_list->fstype, "autofs") == 0)) {
788*7c478bd9Sstevel@tonic-gate 			char *dev_id;
789*7c478bd9Sstevel@tonic-gate 
790*7c478bd9Sstevel@tonic-gate 			dev_id = fs_parse_optlist_for_option(mnt_list->mntopts,
791*7c478bd9Sstevel@tonic-gate 				"dev=", errp);
792*7c478bd9Sstevel@tonic-gate 			if (dev_id == NULL) {
793*7c478bd9Sstevel@tonic-gate 				return;
794*7c478bd9Sstevel@tonic-gate 			}
795*7c478bd9Sstevel@tonic-gate 
796*7c478bd9Sstevel@tonic-gate 			exit = B_FALSE;
797*7c478bd9Sstevel@tonic-gate 			while (tmp != NULL && exit == B_FALSE) {
798*7c478bd9Sstevel@tonic-gate 				if (!(strcmp(tmp->fstype, "autofs")) == 0) {
799*7c478bd9Sstevel@tonic-gate 					char *tmp_dev_id;
800*7c478bd9Sstevel@tonic-gate 
801*7c478bd9Sstevel@tonic-gate 					tmp_dev_id =
802*7c478bd9Sstevel@tonic-gate 						fs_parse_optlist_for_option(
803*7c478bd9Sstevel@tonic-gate 						tmp->mntopts, "dev=", errp);
804*7c478bd9Sstevel@tonic-gate 					if (tmp_dev_id == NULL) {
805*7c478bd9Sstevel@tonic-gate 						return;
806*7c478bd9Sstevel@tonic-gate 					}
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 					if (strcmp(tmp_dev_id, dev_id) == 0) {
809*7c478bd9Sstevel@tonic-gate 						/*
810*7c478bd9Sstevel@tonic-gate 						 * Start searching for an
811*7c478bd9Sstevel@tonic-gate 						 * overlay here.
812*7c478bd9Sstevel@tonic-gate 						 */
813*7c478bd9Sstevel@tonic-gate 						mnt_list->overlayed =
814*7c478bd9Sstevel@tonic-gate 							is_overlayed(tmp,
815*7c478bd9Sstevel@tonic-gate 							mnt_list->mountp);
816*7c478bd9Sstevel@tonic-gate 						exit = B_TRUE;
817*7c478bd9Sstevel@tonic-gate 					}
818*7c478bd9Sstevel@tonic-gate 					free(tmp_dev_id);
819*7c478bd9Sstevel@tonic-gate 				}
820*7c478bd9Sstevel@tonic-gate 				tmp = tmp->next;
821*7c478bd9Sstevel@tonic-gate 			} /* while (tmp != NULL && exit == B_FALSE) */
822*7c478bd9Sstevel@tonic-gate 			free(dev_id);
823*7c478bd9Sstevel@tonic-gate 		} /* if (!(strcmp(mnt_list->fstype, "autofs") == 0)) */
824*7c478bd9Sstevel@tonic-gate 		mnt_list = mnt_list->next;
825*7c478bd9Sstevel@tonic-gate 	} /* while (mnt_list != NULL) */
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate 	if (filtered_list == B_TRUE)
828*7c478bd9Sstevel@tonic-gate 		fs_free_mount_list(mnt_list_to_compare);
829*7c478bd9Sstevel@tonic-gate } /* find_overlayed_filesystems */
830*7c478bd9Sstevel@tonic-gate 
831*7c478bd9Sstevel@tonic-gate static void
832*7c478bd9Sstevel@tonic-gate free_mnttab_entry(struct mnttab *mnttab_entry) {
833*7c478bd9Sstevel@tonic-gate 
834*7c478bd9Sstevel@tonic-gate 	free(mnttab_entry->mnt_special);
835*7c478bd9Sstevel@tonic-gate 	free(mnttab_entry->mnt_mountp);
836*7c478bd9Sstevel@tonic-gate 	free(mnttab_entry->mnt_fstype);
837*7c478bd9Sstevel@tonic-gate 	free(mnttab_entry->mnt_mntopts);
838*7c478bd9Sstevel@tonic-gate 	free(mnttab_entry->mnt_time);
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 	free(mnttab_entry);
841*7c478bd9Sstevel@tonic-gate 
842*7c478bd9Sstevel@tonic-gate } /* free_mnttab_entry */
843*7c478bd9Sstevel@tonic-gate 
844*7c478bd9Sstevel@tonic-gate char *
845*7c478bd9Sstevel@tonic-gate is_option(char *opt_string, char *opt, int *errp) {
846*7c478bd9Sstevel@tonic-gate 	char *equalsign = "=";
847*7c478bd9Sstevel@tonic-gate 	char *found_equalsign;
848*7c478bd9Sstevel@tonic-gate 	char *return_val;
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate 	*errp = 0;
851*7c478bd9Sstevel@tonic-gate 	found_equalsign = strstr(opt, equalsign);
852*7c478bd9Sstevel@tonic-gate 
853*7c478bd9Sstevel@tonic-gate 	/*
854*7c478bd9Sstevel@tonic-gate 	 * If found_equalsign is NULL then we did not find an equal sign
855*7c478bd9Sstevel@tonic-gate 	 * in the option we are to be looking for.
856*7c478bd9Sstevel@tonic-gate 	 */
857*7c478bd9Sstevel@tonic-gate 	if (found_equalsign == NULL) {
858*7c478bd9Sstevel@tonic-gate 		if (strcmp(opt_string, opt) == 0) {
859*7c478bd9Sstevel@tonic-gate 			/*
860*7c478bd9Sstevel@tonic-gate 			 * We have found the option so return with success.
861*7c478bd9Sstevel@tonic-gate 			 */
862*7c478bd9Sstevel@tonic-gate 			return_val = strdup(opt);
863*7c478bd9Sstevel@tonic-gate 			if (return_val == NULL) {
864*7c478bd9Sstevel@tonic-gate 				*errp = errno;
865*7c478bd9Sstevel@tonic-gate 				return (NULL);
866*7c478bd9Sstevel@tonic-gate 			}
867*7c478bd9Sstevel@tonic-gate 		} else {
868*7c478bd9Sstevel@tonic-gate 			return_val = NULL;
869*7c478bd9Sstevel@tonic-gate 		}
870*7c478bd9Sstevel@tonic-gate 	} else {
871*7c478bd9Sstevel@tonic-gate 		int counter = 0;
872*7c478bd9Sstevel@tonic-gate 		char *opt_found;
873*7c478bd9Sstevel@tonic-gate 		char *value;
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate 		opt_found = strstr(opt_string, opt);
876*7c478bd9Sstevel@tonic-gate 
877*7c478bd9Sstevel@tonic-gate 		if (opt_found == NULL) {
878*7c478bd9Sstevel@tonic-gate 			return_val = NULL;
879*7c478bd9Sstevel@tonic-gate 		} else {
880*7c478bd9Sstevel@tonic-gate 			size_t opt_string_len;
881*7c478bd9Sstevel@tonic-gate 			size_t opt_len;
882*7c478bd9Sstevel@tonic-gate 			size_t value_len;
883*7c478bd9Sstevel@tonic-gate 
884*7c478bd9Sstevel@tonic-gate 			opt_string_len = strlen(opt_string);
885*7c478bd9Sstevel@tonic-gate 			opt_len = strlen(opt);
886*7c478bd9Sstevel@tonic-gate 
887*7c478bd9Sstevel@tonic-gate 			value_len = opt_string_len - opt_len;
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate 			value = (char *)calloc((size_t)(value_len+1),
890*7c478bd9Sstevel@tonic-gate 				(size_t)sizeof (char));
891*7c478bd9Sstevel@tonic-gate 
892*7c478bd9Sstevel@tonic-gate 			if (value == NULL) {
893*7c478bd9Sstevel@tonic-gate 				/*
894*7c478bd9Sstevel@tonic-gate 				 * Out of memory
895*7c478bd9Sstevel@tonic-gate 				 */
896*7c478bd9Sstevel@tonic-gate 				*errp = ENOMEM;
897*7c478bd9Sstevel@tonic-gate 				return (NULL);
898*7c478bd9Sstevel@tonic-gate 
899*7c478bd9Sstevel@tonic-gate 			}
900*7c478bd9Sstevel@tonic-gate 
901*7c478bd9Sstevel@tonic-gate 			while (counter <= (value_len-1)) {
902*7c478bd9Sstevel@tonic-gate 				value[counter] = opt_string[opt_len+counter];
903*7c478bd9Sstevel@tonic-gate 				counter = counter + 1;
904*7c478bd9Sstevel@tonic-gate 			}
905*7c478bd9Sstevel@tonic-gate 			/*
906*7c478bd9Sstevel@tonic-gate 			 * Add the null terminating character.
907*7c478bd9Sstevel@tonic-gate 			 */
908*7c478bd9Sstevel@tonic-gate 			value[counter] = '\0';
909*7c478bd9Sstevel@tonic-gate 			return_val = value;
910*7c478bd9Sstevel@tonic-gate 		}
911*7c478bd9Sstevel@tonic-gate 	} /* else */
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate 	return (return_val);
914*7c478bd9Sstevel@tonic-gate } /* is_option */
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 
917*7c478bd9Sstevel@tonic-gate boolean_t
918*7c478bd9Sstevel@tonic-gate is_overlayed(fs_mntlist_t *mnt_list, char *mountp) {
919*7c478bd9Sstevel@tonic-gate 	boolean_t ret_val = B_FALSE;
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 	/*
922*7c478bd9Sstevel@tonic-gate 	 * The first entry in the complete_mnt_list is the same mounted
923*7c478bd9Sstevel@tonic-gate 	 * file system as the one we are trying to determine whether it is
924*7c478bd9Sstevel@tonic-gate 	 * overlayed or not.  There is no need to compare these mounts.
925*7c478bd9Sstevel@tonic-gate 	 */
926*7c478bd9Sstevel@tonic-gate 	mnt_list = mnt_list->next;
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate 	while (mnt_list != NULL && ret_val == B_FALSE) {
929*7c478bd9Sstevel@tonic-gate 		if (!(strcmp(mnt_list->fstype, "autofs") == 0)) {
930*7c478bd9Sstevel@tonic-gate 			if (strcmp(mnt_list->mountp, mountp) == 0) {
931*7c478bd9Sstevel@tonic-gate 				ret_val = B_TRUE;
932*7c478bd9Sstevel@tonic-gate 			} else {
933*7c478bd9Sstevel@tonic-gate 				ret_val = B_FALSE;
934*7c478bd9Sstevel@tonic-gate 			}
935*7c478bd9Sstevel@tonic-gate 		}
936*7c478bd9Sstevel@tonic-gate 		mnt_list = mnt_list->next;
937*7c478bd9Sstevel@tonic-gate 	}
938*7c478bd9Sstevel@tonic-gate 	return (ret_val);
939*7c478bd9Sstevel@tonic-gate } /* is_overlayed */
940