17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*93239addSjohnlev * Common Development and Distribution License (the "License"). 6*93239addSjohnlev * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*93239addSjohnlev * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <stdio.h> 297c478bd9Sstevel@tonic-gate #include <stdarg.h> 307c478bd9Sstevel@tonic-gate #include <stdlib.h> 317c478bd9Sstevel@tonic-gate #include <unistd.h> 327c478bd9Sstevel@tonic-gate #include <libintl.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <fcntl.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 367c478bd9Sstevel@tonic-gate #include <syslog.h> 377c478bd9Sstevel@tonic-gate #include <alloca.h> 387c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 397c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 407c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 417c478bd9Sstevel@tonic-gate #include <sys/mount.h> 427c478bd9Sstevel@tonic-gate #include <sys/filio.h> 437c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_filio.h> 447c478bd9Sstevel@tonic-gate #include <sys/stat.h> 457c478bd9Sstevel@tonic-gate #include <sys/param.h> 467c478bd9Sstevel@tonic-gate #include <zone.h> 477c478bd9Sstevel@tonic-gate #include <signal.h> 487c478bd9Sstevel@tonic-gate #include <strings.h> 497c478bd9Sstevel@tonic-gate #include "fslib.h" 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* LINTLIBRARY */ 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #define BUFLEN 256 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate #define TIME_MAX 16 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* 587c478bd9Sstevel@tonic-gate * Reads all of the entries from the in-kernel mnttab, and returns the 597c478bd9Sstevel@tonic-gate * linked list of the entries. 607c478bd9Sstevel@tonic-gate */ 617c478bd9Sstevel@tonic-gate mntlist_t * 627c478bd9Sstevel@tonic-gate fsgetmntlist(void) 637c478bd9Sstevel@tonic-gate { 647c478bd9Sstevel@tonic-gate FILE *mfp; 657c478bd9Sstevel@tonic-gate mntlist_t *mntl; 667c478bd9Sstevel@tonic-gate char buf[BUFLEN]; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate if ((mfp = fopen(MNTTAB, "r")) == NULL) { 697c478bd9Sstevel@tonic-gate (void) snprintf(buf, BUFLEN, "fsgetmntlist: fopen %s", MNTTAB); 707c478bd9Sstevel@tonic-gate perror(buf); 717c478bd9Sstevel@tonic-gate return (NULL); 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate mntl = fsmkmntlist(mfp); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate (void) fclose(mfp); 777c478bd9Sstevel@tonic-gate return (mntl); 787c478bd9Sstevel@tonic-gate } 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate static struct extmnttab zmnttab = { 0 }; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate struct extmnttab * 847c478bd9Sstevel@tonic-gate fsdupmnttab(struct extmnttab *mnt) 857c478bd9Sstevel@tonic-gate { 867c478bd9Sstevel@tonic-gate struct extmnttab *new; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate new = (struct extmnttab *)malloc(sizeof (*new)); 897c478bd9Sstevel@tonic-gate if (new == NULL) 907c478bd9Sstevel@tonic-gate goto alloc_failed; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate *new = zmnttab; 937c478bd9Sstevel@tonic-gate /* 947c478bd9Sstevel@tonic-gate * Allocate an extra byte for the mountpoint 957c478bd9Sstevel@tonic-gate * name in case a space needs to be added. 967c478bd9Sstevel@tonic-gate */ 977c478bd9Sstevel@tonic-gate new->mnt_mountp = (char *)malloc(strlen(mnt->mnt_mountp) + 2); 987c478bd9Sstevel@tonic-gate if (new->mnt_mountp == NULL) 997c478bd9Sstevel@tonic-gate goto alloc_failed; 1007c478bd9Sstevel@tonic-gate (void) strcpy(new->mnt_mountp, mnt->mnt_mountp); 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate if ((new->mnt_special = strdup(mnt->mnt_special)) == NULL) 1037c478bd9Sstevel@tonic-gate goto alloc_failed; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate if ((new->mnt_fstype = strdup(mnt->mnt_fstype)) == NULL) 1067c478bd9Sstevel@tonic-gate goto alloc_failed; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate if (mnt->mnt_mntopts != NULL) 1097c478bd9Sstevel@tonic-gate if ((new->mnt_mntopts = strdup(mnt->mnt_mntopts)) == NULL) 1107c478bd9Sstevel@tonic-gate goto alloc_failed; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate if (mnt->mnt_time != NULL) 1137c478bd9Sstevel@tonic-gate if ((new->mnt_time = strdup(mnt->mnt_time)) == NULL) 1147c478bd9Sstevel@tonic-gate goto alloc_failed; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate new->mnt_major = mnt->mnt_major; 1177c478bd9Sstevel@tonic-gate new->mnt_minor = mnt->mnt_minor; 1187c478bd9Sstevel@tonic-gate return (new); 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate alloc_failed: 1217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("fsdupmnttab: Out of memory\n")); 1227c478bd9Sstevel@tonic-gate fsfreemnttab(new); 1237c478bd9Sstevel@tonic-gate return (NULL); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * Free a single mnttab structure 1287c478bd9Sstevel@tonic-gate */ 1297c478bd9Sstevel@tonic-gate void 1307c478bd9Sstevel@tonic-gate fsfreemnttab(struct extmnttab *mnt) 1317c478bd9Sstevel@tonic-gate { 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if (mnt) { 1347c478bd9Sstevel@tonic-gate if (mnt->mnt_special) 1357c478bd9Sstevel@tonic-gate free(mnt->mnt_special); 1367c478bd9Sstevel@tonic-gate if (mnt->mnt_mountp) 1377c478bd9Sstevel@tonic-gate free(mnt->mnt_mountp); 1387c478bd9Sstevel@tonic-gate if (mnt->mnt_fstype) 1397c478bd9Sstevel@tonic-gate free(mnt->mnt_fstype); 1407c478bd9Sstevel@tonic-gate if (mnt->mnt_mntopts) 1417c478bd9Sstevel@tonic-gate free(mnt->mnt_mntopts); 1427c478bd9Sstevel@tonic-gate if (mnt->mnt_time) 1437c478bd9Sstevel@tonic-gate free(mnt->mnt_time); 1447c478bd9Sstevel@tonic-gate free(mnt); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate void 1497c478bd9Sstevel@tonic-gate fsfreemntlist(mntlist_t *mntl) 1507c478bd9Sstevel@tonic-gate { 1517c478bd9Sstevel@tonic-gate mntlist_t *mntl_tmp; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate while (mntl) { 1547c478bd9Sstevel@tonic-gate fsfreemnttab(mntl->mntl_mnt); 1557c478bd9Sstevel@tonic-gate mntl_tmp = mntl; 1567c478bd9Sstevel@tonic-gate mntl = mntl->mntl_next; 1577c478bd9Sstevel@tonic-gate free(mntl_tmp); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Read the mnttab file and return it as a list of mnttab structs. 1637c478bd9Sstevel@tonic-gate * Returns NULL if there was a memory failure. 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate mntlist_t * 1667c478bd9Sstevel@tonic-gate fsmkmntlist(FILE *mfp) 1677c478bd9Sstevel@tonic-gate { 1687c478bd9Sstevel@tonic-gate struct extmnttab mnt; 1697c478bd9Sstevel@tonic-gate mntlist_t *mhead, *mtail; 1707c478bd9Sstevel@tonic-gate int ret; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate mhead = mtail = NULL; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate resetmnttab(mfp); 1757c478bd9Sstevel@tonic-gate while ((ret = getextmntent(mfp, &mnt, sizeof (struct extmnttab))) 1767c478bd9Sstevel@tonic-gate != -1) { 1777c478bd9Sstevel@tonic-gate mntlist_t *mp; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate if (ret != 0) /* bad entry */ 1807c478bd9Sstevel@tonic-gate continue; 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate mp = (mntlist_t *)malloc(sizeof (*mp)); 1837c478bd9Sstevel@tonic-gate if (mp == NULL) 1847c478bd9Sstevel@tonic-gate goto alloc_failed; 1857c478bd9Sstevel@tonic-gate if (mhead == NULL) 1867c478bd9Sstevel@tonic-gate mhead = mp; 1877c478bd9Sstevel@tonic-gate else 1887c478bd9Sstevel@tonic-gate mtail->mntl_next = mp; 1897c478bd9Sstevel@tonic-gate mtail = mp; 1907c478bd9Sstevel@tonic-gate mp->mntl_next = NULL; 1917c478bd9Sstevel@tonic-gate mp->mntl_flags = 0; 1927c478bd9Sstevel@tonic-gate if ((mp->mntl_mnt = fsdupmnttab(&mnt)) == NULL) 1937c478bd9Sstevel@tonic-gate goto alloc_failed; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate return (mhead); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate alloc_failed: 1987c478bd9Sstevel@tonic-gate fsfreemntlist(mhead); 1997c478bd9Sstevel@tonic-gate return (NULL); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * Return the last entry that matches mntin's special 2047c478bd9Sstevel@tonic-gate * device and/or mountpt. 2057c478bd9Sstevel@tonic-gate * Helps to be robust here, so we check for NULL pointers. 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate mntlist_t * 2087c478bd9Sstevel@tonic-gate fsgetmlast(mntlist_t *ml, struct mnttab *mntin) 2097c478bd9Sstevel@tonic-gate { 2107c478bd9Sstevel@tonic-gate mntlist_t *delete = NULL; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate for (; ml; ml = ml->mntl_next) { 2137c478bd9Sstevel@tonic-gate if (mntin->mnt_mountp && mntin->mnt_special) { 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * match if and only if both are equal. 2167c478bd9Sstevel@tonic-gate */ 2177c478bd9Sstevel@tonic-gate if ((strcmp(ml->mntl_mnt->mnt_mountp, 2187c478bd9Sstevel@tonic-gate mntin->mnt_mountp) == 0) && 2197c478bd9Sstevel@tonic-gate (strcmp(ml->mntl_mnt->mnt_special, 2207c478bd9Sstevel@tonic-gate mntin->mnt_special) == 0)) 2217c478bd9Sstevel@tonic-gate delete = ml; 2227c478bd9Sstevel@tonic-gate } else if (mntin->mnt_mountp) { 2237c478bd9Sstevel@tonic-gate if (strcmp(ml->mntl_mnt->mnt_mountp, 2247c478bd9Sstevel@tonic-gate mntin->mnt_mountp) == 0) 2257c478bd9Sstevel@tonic-gate delete = ml; 2267c478bd9Sstevel@tonic-gate } else if (mntin->mnt_special) { 2277c478bd9Sstevel@tonic-gate if (strcmp(ml->mntl_mnt->mnt_special, 2287c478bd9Sstevel@tonic-gate mntin->mnt_special) == 0) 2297c478bd9Sstevel@tonic-gate delete = ml; 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate return (delete); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate /* 2377c478bd9Sstevel@tonic-gate * Returns the mountlevel of the pathname in cp. As examples, 2387c478bd9Sstevel@tonic-gate * / => 1, /bin => 2, /bin/ => 2, ////bin////ls => 3, sdf => 0, etc... 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate int 2417c478bd9Sstevel@tonic-gate fsgetmlevel(char *cp) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate int mlevel; 2447c478bd9Sstevel@tonic-gate char *cp1; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate if (cp == NULL || *cp == NULL || *cp != '/') 2477c478bd9Sstevel@tonic-gate return (0); /* this should never happen */ 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate mlevel = 1; /* root (/) is the minimal case */ 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate for (cp1 = cp + 1; *cp1; cp++, cp1++) 2527c478bd9Sstevel@tonic-gate if (*cp == '/' && *cp1 != '/') /* "///" counts as 1 */ 2537c478bd9Sstevel@tonic-gate mlevel++; 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate return (mlevel); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* 2597c478bd9Sstevel@tonic-gate * Returns non-zero if string s is a member of the strings in ps. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate int 2627c478bd9Sstevel@tonic-gate fsstrinlist(const char *s, const char **ps) 2637c478bd9Sstevel@tonic-gate { 2647c478bd9Sstevel@tonic-gate const char *cp; 2657c478bd9Sstevel@tonic-gate cp = *ps; 2667c478bd9Sstevel@tonic-gate while (cp) { 2677c478bd9Sstevel@tonic-gate if (strcmp(s, cp) == 0) 2687c478bd9Sstevel@tonic-gate return (1); 2697c478bd9Sstevel@tonic-gate ps++; 2707c478bd9Sstevel@tonic-gate cp = *ps; 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate return (0); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate static char *empty_opt_vector[] = { 2767c478bd9Sstevel@tonic-gate NULL 2777c478bd9Sstevel@tonic-gate }; 2787c478bd9Sstevel@tonic-gate /* 2797c478bd9Sstevel@tonic-gate * Compare the mount options that were requested by the caller to 2807c478bd9Sstevel@tonic-gate * the options actually supported by the file system. If any requested 2817c478bd9Sstevel@tonic-gate * options are not supported, print a warning message. 2827c478bd9Sstevel@tonic-gate * 2837c478bd9Sstevel@tonic-gate * WARNING: this function modifies the string pointed to by 2847c478bd9Sstevel@tonic-gate * the requested_opts argument. 2857c478bd9Sstevel@tonic-gate * 2867c478bd9Sstevel@tonic-gate * Arguments: 2877c478bd9Sstevel@tonic-gate * requested_opts - the string containing the requested options. 2887c478bd9Sstevel@tonic-gate * actual_opts - the string returned by mount(2), which lists the 2897c478bd9Sstevel@tonic-gate * options actually supported. It is normal for this 2907c478bd9Sstevel@tonic-gate * string to contain more options than the requested options. 2917c478bd9Sstevel@tonic-gate * (The actual options may contain the default options, which 2927c478bd9Sstevel@tonic-gate * may not have been included in the requested options.) 2937c478bd9Sstevel@tonic-gate * special - device being mounted (only used in error messages). 2947c478bd9Sstevel@tonic-gate * mountp - mount point (only used in error messages). 2957c478bd9Sstevel@tonic-gate */ 2967c478bd9Sstevel@tonic-gate void 2977c478bd9Sstevel@tonic-gate cmp_requested_to_actual_options(char *requested_opts, char *actual_opts, 2987c478bd9Sstevel@tonic-gate char *special, char *mountp) 2997c478bd9Sstevel@tonic-gate { 3007c478bd9Sstevel@tonic-gate char *option_ptr, *actopt, *equalptr; 3017c478bd9Sstevel@tonic-gate int found; 3027c478bd9Sstevel@tonic-gate char *actual_opt_hold, *bufp; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate if (requested_opts == NULL) 3057c478bd9Sstevel@tonic-gate return; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate bufp = alloca(strlen(actual_opts) + 1); 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate while (*requested_opts != '\0') { 3107c478bd9Sstevel@tonic-gate (void) getsubopt(&requested_opts, empty_opt_vector, 3117c478bd9Sstevel@tonic-gate &option_ptr); 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate /* 3147c478bd9Sstevel@tonic-gate * Truncate any "=<value>" string from the end of 3157c478bd9Sstevel@tonic-gate * the option. 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate if ((equalptr = strchr(option_ptr, '=')) != NULL) 3187c478bd9Sstevel@tonic-gate *equalptr = '\0'; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate if (*option_ptr == '\0') 3217c478bd9Sstevel@tonic-gate continue; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* 324*93239addSjohnlev * Whilst we don't need this option to perform a lofi 325*93239addSjohnlev * mount, let's not be mendacious enough to complain 326*93239addSjohnlev * about it. 327*93239addSjohnlev */ 328*93239addSjohnlev if (strcmp(option_ptr, "loop") == 0) 329*93239addSjohnlev continue; 330*93239addSjohnlev 331*93239addSjohnlev /* 3327c478bd9Sstevel@tonic-gate * Search for the requested option in the list of options 3337c478bd9Sstevel@tonic-gate * actually supported. 3347c478bd9Sstevel@tonic-gate */ 3357c478bd9Sstevel@tonic-gate found = 0; 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate /* 3387c478bd9Sstevel@tonic-gate * Need to use a copy of actual_opts because getsubopt 3397c478bd9Sstevel@tonic-gate * is destructive and we need to scan the actual_opts 3407c478bd9Sstevel@tonic-gate * string more than once. 3417c478bd9Sstevel@tonic-gate * 3427c478bd9Sstevel@tonic-gate * We also need to reset actual_opt_hold to the 3437c478bd9Sstevel@tonic-gate * beginning of the buffer because getsubopt changes 3447c478bd9Sstevel@tonic-gate * actual_opt_hold (the pointer). 3457c478bd9Sstevel@tonic-gate */ 3467c478bd9Sstevel@tonic-gate actual_opt_hold = bufp; 3477c478bd9Sstevel@tonic-gate if (actual_opts != NULL) 3487c478bd9Sstevel@tonic-gate (void) strcpy(actual_opt_hold, actual_opts); 3497c478bd9Sstevel@tonic-gate else 3507c478bd9Sstevel@tonic-gate *actual_opt_hold = '\0'; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate while (*actual_opt_hold != '\0') { 3537c478bd9Sstevel@tonic-gate (void) getsubopt(&actual_opt_hold, empty_opt_vector, 3547c478bd9Sstevel@tonic-gate &actopt); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* Truncate the "=<value>", if any. */ 3577c478bd9Sstevel@tonic-gate if ((equalptr = strchr(actopt, '=')) != NULL) 3587c478bd9Sstevel@tonic-gate *equalptr = '\0'; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if ((strcmp(option_ptr, actopt)) == 0) { 3617c478bd9Sstevel@tonic-gate found = 1; 3627c478bd9Sstevel@tonic-gate break; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if (found == 0) { 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * That we're ignoring the option is always 3697c478bd9Sstevel@tonic-gate * truthful; the old message that the option 3707c478bd9Sstevel@tonic-gate * was unknown is often not correct. 3717c478bd9Sstevel@tonic-gate */ 3727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3737c478bd9Sstevel@tonic-gate "mount: %s on %s - WARNING ignoring option " 3747c478bd9Sstevel@tonic-gate "\"%s\"\n"), special, mountp, option_ptr); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * FUNCTION: fsgetmaxphys(int *, int *) 3807c478bd9Sstevel@tonic-gate * 3817c478bd9Sstevel@tonic-gate * INPUT: int *maxphys - a pointer to an integer that will hold 3827c478bd9Sstevel@tonic-gate * the value for the system maxphys value. 3837c478bd9Sstevel@tonic-gate * int *error - 0 means completed successfully 3847c478bd9Sstevel@tonic-gate * otherwise this indicates the errno value. 3857c478bd9Sstevel@tonic-gate * 3867c478bd9Sstevel@tonic-gate * RETURNS: int - 0 if maxphys not found 3877c478bd9Sstevel@tonic-gate * - 1 if maxphys is found 3887c478bd9Sstevel@tonic-gate */ 3897c478bd9Sstevel@tonic-gate int 3907c478bd9Sstevel@tonic-gate fsgetmaxphys(int *maxphys, int *error) { 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate int gotit = 0; 3937c478bd9Sstevel@tonic-gate int fp = open("/", O_RDONLY); 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate *error = 0; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * For some reason cannot open root as read only. Need a valid file 3997c478bd9Sstevel@tonic-gate * descriptor to call the ufs private ioctl. If this open failes, 4007c478bd9Sstevel@tonic-gate * just assume we cannot get maxphys in this case. 4017c478bd9Sstevel@tonic-gate */ 4027c478bd9Sstevel@tonic-gate if (fp == -1) { 4037c478bd9Sstevel@tonic-gate return (gotit); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate if (ioctl(fp, _FIOGETMAXPHYS, maxphys) == -1) { 4077c478bd9Sstevel@tonic-gate *error = errno; 4087c478bd9Sstevel@tonic-gate (void) close(fp); 4097c478bd9Sstevel@tonic-gate return (gotit); 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate (void) close(fp); 4137c478bd9Sstevel@tonic-gate gotit = 1; 4147c478bd9Sstevel@tonic-gate return (gotit); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate /* 4197c478bd9Sstevel@tonic-gate * The below is limited support for zone-aware commands. 4207c478bd9Sstevel@tonic-gate */ 4217c478bd9Sstevel@tonic-gate struct zone_summary { 4227c478bd9Sstevel@tonic-gate zoneid_t zoneid; 4237c478bd9Sstevel@tonic-gate char rootpath[MAXPATHLEN]; 4247c478bd9Sstevel@tonic-gate size_t rootpathlen; 4257c478bd9Sstevel@tonic-gate }; 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate struct zone_summary * 4287c478bd9Sstevel@tonic-gate fs_get_zone_summaries(void) 4297c478bd9Sstevel@tonic-gate { 4307c478bd9Sstevel@tonic-gate uint_t numzones = 0, oldnumzones = 0; 4317c478bd9Sstevel@tonic-gate uint_t i, j; 4327c478bd9Sstevel@tonic-gate zoneid_t *ids = NULL; 4337c478bd9Sstevel@tonic-gate struct zone_summary *summaries; 4347c478bd9Sstevel@tonic-gate zoneid_t myzoneid = getzoneid(); 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate for (;;) { 4377c478bd9Sstevel@tonic-gate if (zone_list(ids, &numzones) < 0) { 4387c478bd9Sstevel@tonic-gate perror("unable to retrieve list of zones"); 4397c478bd9Sstevel@tonic-gate if (ids != NULL) 4407c478bd9Sstevel@tonic-gate free(ids); 4417c478bd9Sstevel@tonic-gate return (NULL); 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate if (numzones <= oldnumzones) 4447c478bd9Sstevel@tonic-gate break; 4457c478bd9Sstevel@tonic-gate if (ids != NULL) 4467c478bd9Sstevel@tonic-gate free(ids); 4477c478bd9Sstevel@tonic-gate ids = malloc(numzones * sizeof (*ids)); 4487c478bd9Sstevel@tonic-gate if (ids == NULL) { 4497c478bd9Sstevel@tonic-gate perror("malloc failed"); 4507c478bd9Sstevel@tonic-gate return (NULL); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate oldnumzones = numzones; 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate summaries = malloc((numzones + 1) * sizeof (*summaries)); 4567c478bd9Sstevel@tonic-gate if (summaries == NULL) { 4577c478bd9Sstevel@tonic-gate free(ids); 4587c478bd9Sstevel@tonic-gate perror("malloc failed"); 4597c478bd9Sstevel@tonic-gate return (NULL); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate for (i = 0, j = 0; i < numzones; i++) { 4647c478bd9Sstevel@tonic-gate ssize_t len; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (ids[i] == myzoneid) 4677c478bd9Sstevel@tonic-gate continue; 4687c478bd9Sstevel@tonic-gate len = zone_getattr(ids[i], ZONE_ATTR_ROOT, 4697c478bd9Sstevel@tonic-gate summaries[j].rootpath, sizeof (summaries[j].rootpath)); 4707c478bd9Sstevel@tonic-gate if (len < 0) { 4717c478bd9Sstevel@tonic-gate /* 4727c478bd9Sstevel@tonic-gate * Zone must have gone away. Skip. 4737c478bd9Sstevel@tonic-gate */ 4747c478bd9Sstevel@tonic-gate continue; 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate /* 4777c478bd9Sstevel@tonic-gate * Adding a trailing '/' to the zone's rootpath allows us to 4787c478bd9Sstevel@tonic-gate * use strncmp() to see if a given path resides within that 4797c478bd9Sstevel@tonic-gate * zone. 4807c478bd9Sstevel@tonic-gate * 4817c478bd9Sstevel@tonic-gate * As an example, if the zone's rootpath is "/foo/root", 4827c478bd9Sstevel@tonic-gate * "/foo/root/usr" resides within the zone, while 4837c478bd9Sstevel@tonic-gate * "/foo/rootpath" doesn't. 4847c478bd9Sstevel@tonic-gate */ 4857c478bd9Sstevel@tonic-gate (void) strlcat(summaries[j].rootpath, "/", 4867c478bd9Sstevel@tonic-gate sizeof (summaries[j].rootpath)); 4877c478bd9Sstevel@tonic-gate summaries[j].rootpathlen = len; 4887c478bd9Sstevel@tonic-gate summaries[j].zoneid = ids[i]; 4897c478bd9Sstevel@tonic-gate j++; 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate summaries[j].zoneid = -1; 4927c478bd9Sstevel@tonic-gate free(ids); 4937c478bd9Sstevel@tonic-gate return (summaries); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate static zoneid_t 4977c478bd9Sstevel@tonic-gate fs_find_zone(const struct zone_summary *summaries, const char *mntpt) 4987c478bd9Sstevel@tonic-gate { 4997c478bd9Sstevel@tonic-gate uint_t i; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate for (i = 0; summaries[i].zoneid != -1; i++) { 5027c478bd9Sstevel@tonic-gate if (strncmp(mntpt, summaries[i].rootpath, 5037c478bd9Sstevel@tonic-gate summaries[i].rootpathlen) == 0) 5047c478bd9Sstevel@tonic-gate return (summaries[i].zoneid); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate /* 5077c478bd9Sstevel@tonic-gate * (-1) is the special token we return to the caller if the mount 5087c478bd9Sstevel@tonic-gate * wasn't found in any other mounts on the system. This means it's 5097c478bd9Sstevel@tonic-gate * only visible to our zone. 5107c478bd9Sstevel@tonic-gate * 5117c478bd9Sstevel@tonic-gate * Odd choice of constant, I know, but it beats calling getzoneid() a 5127c478bd9Sstevel@tonic-gate * million times. 5137c478bd9Sstevel@tonic-gate */ 5147c478bd9Sstevel@tonic-gate return (-1); 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate boolean_t 5187c478bd9Sstevel@tonic-gate fs_mount_in_other_zone(const struct zone_summary *summaries, const char *mntpt) 5197c478bd9Sstevel@tonic-gate { 5207c478bd9Sstevel@tonic-gate return (fs_find_zone(summaries, mntpt) != -1); 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate /* 5247c478bd9Sstevel@tonic-gate * List of standard options. 5257c478bd9Sstevel@tonic-gate */ 5267c478bd9Sstevel@tonic-gate static const char *stdopts[] = { 5277c478bd9Sstevel@tonic-gate MNTOPT_RO, MNTOPT_RW, 5287c478bd9Sstevel@tonic-gate MNTOPT_SUID, MNTOPT_NOSUID, 5297c478bd9Sstevel@tonic-gate MNTOPT_DEVICES, MNTOPT_NODEVICES, 5307c478bd9Sstevel@tonic-gate MNTOPT_SETUID, MNTOPT_NOSETUID, 5317c478bd9Sstevel@tonic-gate MNTOPT_NBMAND, MNTOPT_NONBMAND, 5327c478bd9Sstevel@tonic-gate MNTOPT_EXEC, MNTOPT_NOEXEC, 5337c478bd9Sstevel@tonic-gate }; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate #define NSTDOPT (sizeof (stdopts) / sizeof (stdopts[0])) 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate static int 5387c478bd9Sstevel@tonic-gate optindx(const char *opt) 5397c478bd9Sstevel@tonic-gate { 5407c478bd9Sstevel@tonic-gate int i; 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate for (i = 0; i < NSTDOPT; i++) { 5437c478bd9Sstevel@tonic-gate if (strcmp(opt, stdopts[i]) == 0) 5447c478bd9Sstevel@tonic-gate return (i); 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate return (-1); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate /* 5507c478bd9Sstevel@tonic-gate * INPUT: filesystem option not recognized by the fs specific option 5517c478bd9Sstevel@tonic-gate * parsing code. 5527c478bd9Sstevel@tonic-gate * OUTPUT: True if and only if the option is one of the standard VFS 5537c478bd9Sstevel@tonic-gate * layer options. 5547c478bd9Sstevel@tonic-gate */ 5557c478bd9Sstevel@tonic-gate boolean_t 5567c478bd9Sstevel@tonic-gate fsisstdopt(const char *opt) 5577c478bd9Sstevel@tonic-gate { 5587c478bd9Sstevel@tonic-gate return (optindx(opt) != -1); 5597c478bd9Sstevel@tonic-gate } 560