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