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