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