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