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
fs_free_mount_list(fs_mntlist_t * headp)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
fs_get_availablesize(char * mntpnt,int * errp)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
fs_get_avail_for_nonsuperuser_size(char * mntpnt,int * errp)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
fs_get_blocksize(char * mntpnt,int * errp)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 *
fs_get_filtered_mount_list(char * resource,char * mountp,char * fstype,char * mntopts,char * time,boolean_t find_overlays,int * errp)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
fs_get_fragsize(char * mntpnt,int * errp)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
fs_get_maxfilenamelen(char * mntpnt,int * errp)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 *
fs_get_mounts_by_mntopt(char * mntopt,boolean_t find_overlays,int * errp)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 *
fs_get_mount_list(boolean_t find_overlays,int * errp)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
fs_is_readonly(char * mntpnt,int * errp)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 *
fs_parse_optlist_for_option(char * optlist,char * opt,int * errp)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
fs_get_totalsize(char * mntpnt,int * errp)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
fs_get_usedsize(char * mntpnt,int * errp)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 *
create_mntlist_entry(struct mnttab mnttab_entry)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 *
create_extmntlist_entry(struct extmnttab mnttab_entry)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 *
create_mnttab_filter(char * resource,char * mountp,char * fstype,char * mntopts,char * time)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
find_overlayed_filesystems(fs_mntlist_t * mnt_list,boolean_t filtered_list,int * errp)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
free_mnttab_entry(struct mnttab * mnttab_entry)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 *
is_option(char * opt_string,char * opt,int * errp)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
is_overlayed(fs_mntlist_t * mnt_list,char * mountp)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