xref: /titanic_44/usr/src/lib/libfsmgt/common/fs_mounts.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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
fs_free_mount_list(fs_mntlist_t * headp)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
fs_get_availablesize(char * mntpnt,int * errp)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
fs_get_avail_for_nonsuperuser_size(char * mntpnt,int * errp)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
fs_get_blocksize(char * mntpnt,int * errp)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 *
fs_get_filtered_mount_list(char * resource,char * mountp,char * fstype,char * mntopts,char * time,boolean_t find_overlays,int * errp)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
fs_get_fragsize(char * mntpnt,int * errp)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
fs_get_maxfilenamelen(char * mntpnt,int * errp)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 *
fs_get_mounts_by_mntopt(char * mntopt,boolean_t find_overlays,int * errp)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 *
fs_get_mount_list(boolean_t find_overlays,int * errp)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
fs_is_readonly(char * mntpnt,int * errp)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 *
fs_parse_optlist_for_option(char * optlist,char * opt,int * errp)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
fs_get_totalsize(char * mntpnt,int * errp)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
fs_get_usedsize(char * mntpnt,int * errp)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 *
create_mntlist_entry(struct mnttab mnttab_entry)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 *
create_extmntlist_entry(struct extmnttab mnttab_entry)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 *
create_mnttab_filter(char * resource,char * mountp,char * fstype,char * mntopts,char * time)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
find_overlayed_filesystems(fs_mntlist_t * mnt_list,boolean_t filtered_list,int * errp)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
free_mnttab_entry(struct mnttab * mnttab_entry)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 *
is_option(char * opt_string,char * opt,int * errp)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
is_overlayed(fs_mntlist_t * mnt_list,char * mountp)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