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