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 54bff34e3Sthurlow * Common Development and Distribution License (the "License"). 64bff34e3Sthurlow * 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 /* 227c478bd9Sstevel@tonic-gate * autod_parse.c 237c478bd9Sstevel@tonic-gate * 244bff34e3Sthurlow * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 26*bd93c05dSAlexander Eremin * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <ctype.h> 317c478bd9Sstevel@tonic-gate #include <string.h> 327c478bd9Sstevel@tonic-gate #include <syslog.h> 337c478bd9Sstevel@tonic-gate #include <sys/types.h> 347c478bd9Sstevel@tonic-gate #include <sys/stat.h> 357c478bd9Sstevel@tonic-gate #include <sys/param.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <pwd.h> 387c478bd9Sstevel@tonic-gate #include <netinet/in.h> 397c478bd9Sstevel@tonic-gate #include <netdb.h> 407c478bd9Sstevel@tonic-gate #include <sys/tiuser.h> 417c478bd9Sstevel@tonic-gate #include <locale.h> 427c478bd9Sstevel@tonic-gate #include <stdlib.h> 437c478bd9Sstevel@tonic-gate #include <unistd.h> 447c478bd9Sstevel@tonic-gate #include <thread.h> 457c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 467c478bd9Sstevel@tonic-gate #include <rpcsvc/mount.h> 477c478bd9Sstevel@tonic-gate #include <fcntl.h> 487c478bd9Sstevel@tonic-gate #include <limits.h> 497c478bd9Sstevel@tonic-gate #include "automount.h" 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* 527c478bd9Sstevel@tonic-gate * This structure is used to determine the hierarchical 537c478bd9Sstevel@tonic-gate * relationship between directories 547c478bd9Sstevel@tonic-gate */ 5511606941Sjwahlig typedef struct _hiernode { 567c478bd9Sstevel@tonic-gate char dirname[MAXFILENAMELEN+1]; 577c478bd9Sstevel@tonic-gate struct _hiernode *subdir; 587c478bd9Sstevel@tonic-gate struct _hiernode *leveldir; 597c478bd9Sstevel@tonic-gate struct mapent *mapent; 6011606941Sjwahlig } hiernode; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate void free_mapent(struct mapent *); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate static int mapline_to_mapent(struct mapent **, struct mapline *, char *, char *, 657c478bd9Sstevel@tonic-gate char *, char *, uint_t); 667c478bd9Sstevel@tonic-gate static int hierarchical_sort(struct mapent *, hiernode **, char *, char *); 677c478bd9Sstevel@tonic-gate static int push_options(hiernode *, char *, char *, int); 687c478bd9Sstevel@tonic-gate static int set_mapent_opts(struct mapent *, char *, char *, char *); 697c478bd9Sstevel@tonic-gate static void get_opts(char *, char *, char *, bool_t *); 707c478bd9Sstevel@tonic-gate static int fstype_opts(struct mapent *, char *, char *, char *); 717c478bd9Sstevel@tonic-gate static int modify_mapents(struct mapent **, char *, char *, char *, hiernode *, 727c478bd9Sstevel@tonic-gate char *, uint_t, bool_t); 737c478bd9Sstevel@tonic-gate static int set_and_fake_mapent_mntlevel(hiernode *, char *, char *, char *, 747c478bd9Sstevel@tonic-gate struct mapent **, uint_t, char *, bool_t); 757c478bd9Sstevel@tonic-gate static int mark_level1_root(hiernode *, char *); 767c478bd9Sstevel@tonic-gate static int mark_and_fake_level1_noroot(hiernode *, char *, char *, char *, 777c478bd9Sstevel@tonic-gate struct mapent **, uint_t i, char *); 787c478bd9Sstevel@tonic-gate static int convert_mapent_to_automount(struct mapent *, char *, char *); 797c478bd9Sstevel@tonic-gate static int automount_opts(char **, char *); 807c478bd9Sstevel@tonic-gate static int parse_fsinfo(char *, struct mapent *); 817c478bd9Sstevel@tonic-gate static int parse_nfs(char *, struct mapent *, char *, char *, char **, char **, 827c478bd9Sstevel@tonic-gate int); 837c478bd9Sstevel@tonic-gate static int parse_special(struct mapent *, char *, char *, char **, char **, 847c478bd9Sstevel@tonic-gate int); 857c478bd9Sstevel@tonic-gate static int get_dir_from_path(char *, char **, int); 867c478bd9Sstevel@tonic-gate static int alloc_hiernode(hiernode **, char *); 877c478bd9Sstevel@tonic-gate static void free_hiernode(hiernode *); 887c478bd9Sstevel@tonic-gate static void trace_mapents(char *, struct mapent *); 897c478bd9Sstevel@tonic-gate static void trace_hierarchy(hiernode *, int); 907c478bd9Sstevel@tonic-gate static struct mapent *do_mapent_hosts(char *, char *, uint_t); 917c478bd9Sstevel@tonic-gate static void freeex_ent(struct exportnode *); 927c478bd9Sstevel@tonic-gate static void freeex(struct exportnode *); 937c478bd9Sstevel@tonic-gate static void dump_mapent_err(struct mapent *, char *, char *); 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate #define PARSE_OK 0 967c478bd9Sstevel@tonic-gate #define PARSE_ERROR -1 977c478bd9Sstevel@tonic-gate #define MAX_FSLEN 32 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * mapentry error type defininitions 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate #define MAPENT_NOERR 0 1037c478bd9Sstevel@tonic-gate #define MAPENT_UATFS 1 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * parse_entry(char *key, char *mapname, char *mapopts, struct mapline *ml, 1077c478bd9Sstevel@tonic-gate * char *subdir, uint_t isdirect, bool_t mount_access) 1087c478bd9Sstevel@tonic-gate * Parses the data in ml to build a mapentry list containing the information 1097c478bd9Sstevel@tonic-gate * for the mounts/lookups to be performed. Builds an intermediate mapentry list 1107c478bd9Sstevel@tonic-gate * by processing ml, hierarchically sorts (builds a tree of) the list according 1117c478bd9Sstevel@tonic-gate * to mountpoint. Then pushes options down the hierarchy, and fills in the mount 1127c478bd9Sstevel@tonic-gate * file system. Finally, modifies the intermediate list depending on how far 1137c478bd9Sstevel@tonic-gate * in the hierarchy the current request is (uses subdir). Deals with special 1147c478bd9Sstevel@tonic-gate * case of /net map parsing. 1157c478bd9Sstevel@tonic-gate * Returns a pointer to the head of the mapentry list. 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate struct mapent * 1187c478bd9Sstevel@tonic-gate parse_entry(char *key, char *mapname, char *mapopts, struct mapline *ml, 1197c478bd9Sstevel@tonic-gate char *subdir, uint_t isdirect, bool_t mount_access) 1207c478bd9Sstevel@tonic-gate { 1217c478bd9Sstevel@tonic-gate char *p; 1227c478bd9Sstevel@tonic-gate char defaultopts[AUTOFS_MAXOPTSLEN]; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate struct mapent *mapents = NULL; 1257c478bd9Sstevel@tonic-gate hiernode *rootnode = NULL; 1267c478bd9Sstevel@tonic-gate char *lp = ml->linebuf; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate if (trace > 1) 1297c478bd9Sstevel@tonic-gate trace_prt(1, " mapline: %s\n", ml->linebuf); 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * Assure the key is only one token long. 1337c478bd9Sstevel@tonic-gate * This prevents options from sneaking in through the 1347c478bd9Sstevel@tonic-gate * command line or corruption of /etc/mnttab. 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate for (p = key; *p != '\0'; p++) { 1377c478bd9Sstevel@tonic-gate if (isspace(*p)) { 1387c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 1397c478bd9Sstevel@tonic-gate "parse_entry: bad key in map %s: %s", mapname, key); 1407c478bd9Sstevel@tonic-gate return ((struct mapent *)NULL); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * select the appropriate parser, and build the mapentry list 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate if (strcmp(lp, "-hosts") == 0) { 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * the /net parser - uses do_mapent_hosts to build mapents. 1507c478bd9Sstevel@tonic-gate * The mapopts are considered default for every entry, so we 1517c478bd9Sstevel@tonic-gate * don't push options down hierarchies. 1527c478bd9Sstevel@tonic-gate */ 1537c478bd9Sstevel@tonic-gate mapents = do_mapent_hosts(mapopts, key, isdirect); 1547c478bd9Sstevel@tonic-gate if (mapents == NULL) /* nothing to free */ 1557c478bd9Sstevel@tonic-gate return (mapents); 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate if (trace > 3) 1587c478bd9Sstevel@tonic-gate trace_mapents("do_mapent_hosts:(return)", mapents); 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate if (hierarchical_sort(mapents, &rootnode, key, mapname) 1617c478bd9Sstevel@tonic-gate != PARSE_OK) 1627c478bd9Sstevel@tonic-gate goto parse_error; 1637c478bd9Sstevel@tonic-gate } else { 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * all other parsing 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate if (mapline_to_mapent(&mapents, ml, key, mapname, 1687c478bd9Sstevel@tonic-gate mapopts, defaultopts, isdirect) != PARSE_OK) 1697c478bd9Sstevel@tonic-gate goto parse_error; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate if (mapents == NULL) 1727c478bd9Sstevel@tonic-gate return (mapents); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate if (hierarchical_sort(mapents, &rootnode, key, mapname) 1757c478bd9Sstevel@tonic-gate != PARSE_OK) 1767c478bd9Sstevel@tonic-gate goto parse_error; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate if (push_options(rootnode, defaultopts, mapopts, 1797c478bd9Sstevel@tonic-gate MAPENT_NOERR) != PARSE_OK) 1807c478bd9Sstevel@tonic-gate goto parse_error; 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate if (trace > 3) { 1837c478bd9Sstevel@tonic-gate trace_prt(1, "\n\tpush_options (return)\n"); 1847c478bd9Sstevel@tonic-gate trace_prt(0, "\tdefault options=%s\n", defaultopts); 1857c478bd9Sstevel@tonic-gate trace_hierarchy(rootnode, 0); 1867c478bd9Sstevel@tonic-gate }; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (parse_fsinfo(mapname, mapents) != PARSE_OK) 1897c478bd9Sstevel@tonic-gate goto parse_error; 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate /* 1937c478bd9Sstevel@tonic-gate * Modify the mapentry list. We *must* do this only after 1947c478bd9Sstevel@tonic-gate * the mapentry list is completely built (since we need to 1957c478bd9Sstevel@tonic-gate * have parse_fsinfo called first). 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate if (modify_mapents(&mapents, mapname, mapopts, subdir, 1987c478bd9Sstevel@tonic-gate rootnode, key, isdirect, mount_access) != PARSE_OK) 1997c478bd9Sstevel@tonic-gate goto parse_error; 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * XXX: its dangerous to use rootnode after modify mapents as 2037c478bd9Sstevel@tonic-gate * it may be pointing to mapents that have been freed 2047c478bd9Sstevel@tonic-gate */ 2057c478bd9Sstevel@tonic-gate if (rootnode != NULL) 2067c478bd9Sstevel@tonic-gate free_hiernode(rootnode); 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate return (mapents); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate parse_error: 2117c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "parse_entry: mapentry parse error: map=%s key=%s", 2127c478bd9Sstevel@tonic-gate mapname, key); 2137c478bd9Sstevel@tonic-gate free_mapent(mapents); 2147c478bd9Sstevel@tonic-gate if (rootnode != NULL) 2157c478bd9Sstevel@tonic-gate free_hiernode(rootnode); 2167c478bd9Sstevel@tonic-gate return ((struct mapent *)NULL); 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* 2217c478bd9Sstevel@tonic-gate * mapline_to_mapent(struct mapent **mapents, struct mapline *ml, 2227c478bd9Sstevel@tonic-gate * char *key, char *mapname, char *mapopts, char *defaultopts, 2237c478bd9Sstevel@tonic-gate * uint_t isdirect) 2247c478bd9Sstevel@tonic-gate * Parses the mapline information in ml word by word to build an intermediate 2257c478bd9Sstevel@tonic-gate * mapentry list, which is passed back to the caller. The mapentries may have 2267c478bd9Sstevel@tonic-gate * holes (example no options), as they are completed only later. The logic is 2277c478bd9Sstevel@tonic-gate * awkward, but needed to provide the supported flexibility in the map entries. 2287c478bd9Sstevel@tonic-gate * (especially the first line). Note that the key is the full pathname of the 2297c478bd9Sstevel@tonic-gate * directory to be mounted in a direct map, and ml is the mapentry beyond key. 2307c478bd9Sstevel@tonic-gate * Returns PARSE_OK or an appropriate error value. 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate static int 2337c478bd9Sstevel@tonic-gate mapline_to_mapent(struct mapent **mapents, struct mapline *ml, char *key, 2347c478bd9Sstevel@tonic-gate char *mapname, char *mapopts, char *defaultopts, 2357c478bd9Sstevel@tonic-gate uint_t isdirect) 2367c478bd9Sstevel@tonic-gate { 2377c478bd9Sstevel@tonic-gate struct mapent *me = NULL; 2387c478bd9Sstevel@tonic-gate struct mapent *mp; 2397c478bd9Sstevel@tonic-gate char w[MAXPATHLEN]; 2407c478bd9Sstevel@tonic-gate char wq[MAXPATHLEN]; 2417c478bd9Sstevel@tonic-gate char w1[MAXPATHLEN]; 2427c478bd9Sstevel@tonic-gate int implied; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate char *lp = ml->linebuf; 2457c478bd9Sstevel@tonic-gate char *lq = ml->lineqbuf; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* do any macro expansions that are required to complete ml */ 2487c478bd9Sstevel@tonic-gate if (macro_expand(key, lp, lq, LINESZ)) { 2497c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 2507c478bd9Sstevel@tonic-gate "mapline_to_mapent: map %s: line too long (max %d chars)", 2517c478bd9Sstevel@tonic-gate mapname, LINESZ - 1); 2527c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate if (trace > 3 && (strcmp(ml->linebuf, lp) != 0)) 2557c478bd9Sstevel@tonic-gate trace_prt(1, 2567c478bd9Sstevel@tonic-gate " mapline_to_mapent: (expanded) mapline (%s,%s)\n", 2577c478bd9Sstevel@tonic-gate ml->linebuf, ml->lineqbuf); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* init the head of mapentry list to null */ 2607c478bd9Sstevel@tonic-gate *mapents = NULL; 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * Get the first word - its either a '-' if default options provided, 2647c478bd9Sstevel@tonic-gate * a '/', if the mountroot is implicitly provided, or a mount filesystem 2657c478bd9Sstevel@tonic-gate * if the mountroot is implicit. Note that if the first word begins with 2667c478bd9Sstevel@tonic-gate * a '-' then the second must be read and it must be a mountpoint or a 2677c478bd9Sstevel@tonic-gate * mount filesystem. Use mapopts if no default opts are provided. 2687c478bd9Sstevel@tonic-gate */ 2697c478bd9Sstevel@tonic-gate if (getword(w, wq, &lp, &lq, ' ', sizeof (w)) == -1) 2707c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 2717c478bd9Sstevel@tonic-gate if (*w == '-') { 2727c478bd9Sstevel@tonic-gate strcpy(defaultopts, w); 2737c478bd9Sstevel@tonic-gate if (getword(w, wq, &lp, &lq, ' ', sizeof (w)) == -1) 2747c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 2757c478bd9Sstevel@tonic-gate } else 2767c478bd9Sstevel@tonic-gate strcpy(defaultopts, mapopts); 2777c478bd9Sstevel@tonic-gate 2784bff34e3Sthurlow /* 27924101b26SRobert Thurlow * implied is true if there is no '/' 28024101b26SRobert Thurlow * We need the same code path if we have an smbfs mount. 2814bff34e3Sthurlow */ 28224101b26SRobert Thurlow implied = (*w != '/') || (strstr(defaultopts, "fstype=smbfs") != NULL); 2837c478bd9Sstevel@tonic-gate while (*w == '/' || implied) { 2847c478bd9Sstevel@tonic-gate mp = me; 2857c478bd9Sstevel@tonic-gate if ((me = (struct mapent *)malloc(sizeof (*me))) == NULL) 2867c478bd9Sstevel@tonic-gate goto alloc_failed; 2877c478bd9Sstevel@tonic-gate (void) memset((char *)me, 0, sizeof (*me)); 2887c478bd9Sstevel@tonic-gate if (*mapents == NULL) /* special case of head */ 2897c478bd9Sstevel@tonic-gate *mapents = me; 2907c478bd9Sstevel@tonic-gate else 2917c478bd9Sstevel@tonic-gate mp->map_next = me; 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * direct maps get an empty string as root - to be filled 2957c478bd9Sstevel@tonic-gate * by the entire path later. Indirect maps get /key as the 2967c478bd9Sstevel@tonic-gate * map root. Note that xfn maps don't care about the root 2977c478bd9Sstevel@tonic-gate * - they override it in getmapent_fn(). 2987c478bd9Sstevel@tonic-gate */ 2997c478bd9Sstevel@tonic-gate if (isdirect) { 3007c478bd9Sstevel@tonic-gate *w1 = '\0'; 3017c478bd9Sstevel@tonic-gate } else { 3027c478bd9Sstevel@tonic-gate strcpy(w1, "/"); 3037c478bd9Sstevel@tonic-gate strcat(w1, key); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate if ((me->map_root = strdup(w1)) == NULL) 3067c478bd9Sstevel@tonic-gate goto alloc_failed; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate /* mntpnt is empty for the mount root */ 3097c478bd9Sstevel@tonic-gate if (strcmp(w, "/") == 0 || implied) 3107c478bd9Sstevel@tonic-gate me->map_mntpnt = strdup(""); 3117c478bd9Sstevel@tonic-gate else 3127c478bd9Sstevel@tonic-gate me->map_mntpnt = strdup(w); 3137c478bd9Sstevel@tonic-gate if (me->map_mntpnt == NULL) 3147c478bd9Sstevel@tonic-gate goto alloc_failed; 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * If implied, the word must be a mount filesystem, 3187c478bd9Sstevel@tonic-gate * and its already read in; also turn off implied - its 3197c478bd9Sstevel@tonic-gate * not applicable except for the mount root. Else, 3207c478bd9Sstevel@tonic-gate * read another (or two) words depending on if there's 3217c478bd9Sstevel@tonic-gate * an option. 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate if (implied) /* must be a mount filesystem */ 3247c478bd9Sstevel@tonic-gate implied = 0; 3257c478bd9Sstevel@tonic-gate else { 3267c478bd9Sstevel@tonic-gate if (getword(w, wq, &lp, &lq, ' ', sizeof (w)) == -1) 3277c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 3287c478bd9Sstevel@tonic-gate if (w[0] == '-') { 3297c478bd9Sstevel@tonic-gate /* mount options */ 3307c478bd9Sstevel@tonic-gate if ((me->map_mntopts = strdup(w)) == NULL) 3317c478bd9Sstevel@tonic-gate goto alloc_failed; 3327c478bd9Sstevel@tonic-gate if (getword(w, wq, &lp, &lq, ' ', 3337c478bd9Sstevel@tonic-gate sizeof (w)) == -1) 3347c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate /* 3397c478bd9Sstevel@tonic-gate * must be a mount filesystem or a set of filesystems at 3407c478bd9Sstevel@tonic-gate * this point. 3417c478bd9Sstevel@tonic-gate */ 3427c478bd9Sstevel@tonic-gate if (w[0] == '\0' || w[0] == '-') { 3437c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3447c478bd9Sstevel@tonic-gate "mapline_to_mapent: bad location=%s map=%s key=%s", 3457c478bd9Sstevel@tonic-gate w, mapname, key); 3467c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* 3507c478bd9Sstevel@tonic-gate * map_fsw and map_fswq hold information which will be 3517c478bd9Sstevel@tonic-gate * used to determine filesystem information at a later 3527c478bd9Sstevel@tonic-gate * point. This is required since we can only find out 3537c478bd9Sstevel@tonic-gate * about the mount file system after the directories 3547c478bd9Sstevel@tonic-gate * are hierarchically sorted and options have been pushed 3557c478bd9Sstevel@tonic-gate * down the hierarchies. 3567c478bd9Sstevel@tonic-gate */ 3577c478bd9Sstevel@tonic-gate if (((me->map_fsw = strdup(w)) == NULL) || 3587c478bd9Sstevel@tonic-gate ((me->map_fswq = strdup(wq)) == NULL)) 3597c478bd9Sstevel@tonic-gate goto alloc_failed; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate /* 3627c478bd9Sstevel@tonic-gate * the next word, if any, is either another mount point or a 3637c478bd9Sstevel@tonic-gate * mount filesystem if more than one server is listed. 3647c478bd9Sstevel@tonic-gate */ 3657c478bd9Sstevel@tonic-gate if (getword(w, wq, &lp, &lq, ' ', sizeof (w)) == -1) 3667c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 3677c478bd9Sstevel@tonic-gate while (*w && *w != '/') { /* more than 1 server listed */ 3687c478bd9Sstevel@tonic-gate int len; 3697c478bd9Sstevel@tonic-gate char *fsw, *fswq; 3707c478bd9Sstevel@tonic-gate len = strlen(me->map_fsw) + strlen(w) + 4; 3717c478bd9Sstevel@tonic-gate if ((fsw = (char *)malloc(len)) == NULL) 3727c478bd9Sstevel@tonic-gate goto alloc_failed; 3737c478bd9Sstevel@tonic-gate sprintf(fsw, "%s %s", me->map_fsw, w); 3747c478bd9Sstevel@tonic-gate free(me->map_fsw); 3757c478bd9Sstevel@tonic-gate me->map_fsw = fsw; 3767c478bd9Sstevel@tonic-gate len = strlen(me->map_fswq) + strlen(wq) + 4; 3777c478bd9Sstevel@tonic-gate if ((fswq = (char *)malloc(len)) == NULL) 3787c478bd9Sstevel@tonic-gate goto alloc_failed; 3797c478bd9Sstevel@tonic-gate sprintf(fswq, "%s %s", me->map_fswq, wq); 3807c478bd9Sstevel@tonic-gate free(me->map_fswq); 3817c478bd9Sstevel@tonic-gate me->map_fswq = fswq; 3827c478bd9Sstevel@tonic-gate if (getword(w, wq, &lp, &lq, ' ', sizeof (w)) == -1) 3837c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate /* initialize flags */ 3877c478bd9Sstevel@tonic-gate me->map_mntlevel = -1; 3887c478bd9Sstevel@tonic-gate me->map_modified = FALSE; 3897c478bd9Sstevel@tonic-gate me->map_faked = FALSE; 3907c478bd9Sstevel@tonic-gate me->map_err = MAPENT_NOERR; 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate me->map_next = NULL; 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate if (*mapents == NULL || w[0] != '\0') { /* sanity check */ 3967c478bd9Sstevel@tonic-gate if (verbose) { 3977c478bd9Sstevel@tonic-gate if (*mapents == NULL) 3987c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3997c478bd9Sstevel@tonic-gate "mapline_to_mapent: parsed with null mapents"); 4007c478bd9Sstevel@tonic-gate else 4017c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 4027c478bd9Sstevel@tonic-gate "mapline_to_mapent: parsed nononempty w=%s", w); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if (trace > 3) 4087c478bd9Sstevel@tonic-gate trace_mapents("mapline_to_mapent:", *mapents); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate return (PARSE_OK); 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate alloc_failed: 4137c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "mapline_to_mapent: Memory allocation failed"); 4147c478bd9Sstevel@tonic-gate return (ENOMEM); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate /* 4187c478bd9Sstevel@tonic-gate * hierarchical_sort(struct mapent *mapents, hiernode **rootnode, char *key 4197c478bd9Sstevel@tonic-gate * char *mapname) 4207c478bd9Sstevel@tonic-gate * sorts the mntpnts in each mapent to build a hierarchy of nodes, with 4217c478bd9Sstevel@tonic-gate * with the rootnode being the mount root. The hierarchy is setup as 4227c478bd9Sstevel@tonic-gate * levels, and subdirs below each level. Provides a link from node to 4237c478bd9Sstevel@tonic-gate * the relevant mapentry. 4247c478bd9Sstevel@tonic-gate * Returns PARSE_OK or appropriate error value 4257c478bd9Sstevel@tonic-gate */ 4267c478bd9Sstevel@tonic-gate static int 4277c478bd9Sstevel@tonic-gate hierarchical_sort(struct mapent *mapents, hiernode **rootnode, char *key, 4287c478bd9Sstevel@tonic-gate char *mapname) 4297c478bd9Sstevel@tonic-gate { 4307c478bd9Sstevel@tonic-gate hiernode *prevnode, *currnode, *newnode; 4317c478bd9Sstevel@tonic-gate char *path; 4327c478bd9Sstevel@tonic-gate char dirname[MAXFILENAMELEN]; 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate int rc = PARSE_OK; 4357c478bd9Sstevel@tonic-gate struct mapent *me = mapents; 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate /* allocate the rootnode with a default path of "" */ 4387c478bd9Sstevel@tonic-gate *rootnode = NULL; 4397c478bd9Sstevel@tonic-gate if ((rc = alloc_hiernode(rootnode, "")) != PARSE_OK) 4407c478bd9Sstevel@tonic-gate return (rc); 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* 4437c478bd9Sstevel@tonic-gate * walk through mapents - for each mapent, locate the position 4447c478bd9Sstevel@tonic-gate * within the hierarchy by walking across leveldirs, and 4457c478bd9Sstevel@tonic-gate * subdirs of matched leveldirs. Starts one level below 4467c478bd9Sstevel@tonic-gate * the root (assumes an implicit match with rootnode). 4477c478bd9Sstevel@tonic-gate * XXX - this could probably be done more cleanly using recursion. 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate while (me != NULL) { 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate path = me->map_mntpnt; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate if ((rc = get_dir_from_path(dirname, &path, 4547c478bd9Sstevel@tonic-gate sizeof (dirname))) != PARSE_OK) 4557c478bd9Sstevel@tonic-gate return (rc); 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate prevnode = *rootnode; 4587c478bd9Sstevel@tonic-gate currnode = (*rootnode)->subdir; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate while (dirname[0] != '\0') { 4617c478bd9Sstevel@tonic-gate if (currnode != NULL) { 4627c478bd9Sstevel@tonic-gate if (strcmp(currnode->dirname, dirname) == 0) { 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * match found - mntpnt is a child of 4657c478bd9Sstevel@tonic-gate * this node 4667c478bd9Sstevel@tonic-gate */ 4677c478bd9Sstevel@tonic-gate prevnode = currnode; 4687c478bd9Sstevel@tonic-gate currnode = currnode->subdir; 4697c478bd9Sstevel@tonic-gate } else { 4707c478bd9Sstevel@tonic-gate prevnode = currnode; 4717c478bd9Sstevel@tonic-gate currnode = currnode->leveldir; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate if (currnode == NULL) { 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * No more leveldirs to match. 4767c478bd9Sstevel@tonic-gate * Add a new one 4777c478bd9Sstevel@tonic-gate */ 4787c478bd9Sstevel@tonic-gate if ((rc = alloc_hiernode 4797c478bd9Sstevel@tonic-gate (&newnode, dirname)) 4807c478bd9Sstevel@tonic-gate != PARSE_OK) 4817c478bd9Sstevel@tonic-gate return (rc); 4827c478bd9Sstevel@tonic-gate prevnode->leveldir = newnode; 4837c478bd9Sstevel@tonic-gate prevnode = newnode; 4847c478bd9Sstevel@tonic-gate currnode = newnode->subdir; 4857c478bd9Sstevel@tonic-gate } else { 4867c478bd9Sstevel@tonic-gate /* try this leveldir */ 4877c478bd9Sstevel@tonic-gate continue; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate } else { 4917c478bd9Sstevel@tonic-gate /* no more subdirs to match. Add a new one */ 4927c478bd9Sstevel@tonic-gate if ((rc = alloc_hiernode(&newnode, 4937c478bd9Sstevel@tonic-gate dirname)) != PARSE_OK) 4947c478bd9Sstevel@tonic-gate return (rc); 4957c478bd9Sstevel@tonic-gate prevnode->subdir = newnode; 4967c478bd9Sstevel@tonic-gate prevnode = newnode; 4977c478bd9Sstevel@tonic-gate currnode = newnode->subdir; 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate if ((rc = get_dir_from_path(dirname, &path, 5007c478bd9Sstevel@tonic-gate sizeof (dirname))) != PARSE_OK) 5017c478bd9Sstevel@tonic-gate return (rc); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate if (prevnode->mapent != NULL) { 5057c478bd9Sstevel@tonic-gate /* duplicate mntpoint found */ 5067c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 5077c478bd9Sstevel@tonic-gate "hierarchical_sort: duplicate mntpnt map=%s key=%s", 5087c478bd9Sstevel@tonic-gate mapname, key); 5097c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate /* provide a pointer from node to mapent */ 5137c478bd9Sstevel@tonic-gate prevnode->mapent = me; 5147c478bd9Sstevel@tonic-gate me = me->map_next; 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate if (trace > 3) { 5187c478bd9Sstevel@tonic-gate trace_prt(1, "\n\thierarchical_sort:\n"); 5197c478bd9Sstevel@tonic-gate trace_hierarchy(*rootnode, 0); /* 0 is rootnode's level */ 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate return (rc); 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* 5267c478bd9Sstevel@tonic-gate * push_options(hiernode *node, char *opts, char *mapopts, int err) 5277c478bd9Sstevel@tonic-gate * Pushes the options down a hierarchical structure. Works recursively from the 5287c478bd9Sstevel@tonic-gate * root, which is passed in on the first call. Uses a replacement policy. 5297c478bd9Sstevel@tonic-gate * If a node points to a mapentry, and it has an option, then thats the option 5307c478bd9Sstevel@tonic-gate * for that mapentry. Else, the node's mapent inherits the option from the 5317c478bd9Sstevel@tonic-gate * default (which may be the global option for the entry or mapopts). 5327c478bd9Sstevel@tonic-gate * err is useful in flagging entries with errors in pushing options. 5337c478bd9Sstevel@tonic-gate * returns PARSE_OK or appropriate error value. 5347c478bd9Sstevel@tonic-gate */ 5357c478bd9Sstevel@tonic-gate static int 5367c478bd9Sstevel@tonic-gate push_options(hiernode *node, char *defaultopts, char *mapopts, int err) 5377c478bd9Sstevel@tonic-gate { 5387c478bd9Sstevel@tonic-gate int rc = PARSE_OK; 5397c478bd9Sstevel@tonic-gate struct mapent *me = NULL; 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate /* ensure that all the dirs at a level are passed the default options */ 5427c478bd9Sstevel@tonic-gate while (node != NULL) { 5437c478bd9Sstevel@tonic-gate me = node->mapent; 5447c478bd9Sstevel@tonic-gate if (me != NULL) { /* not all nodes point to a mapentry */ 5457c478bd9Sstevel@tonic-gate me->map_err = err; 5467c478bd9Sstevel@tonic-gate if ((rc = set_mapent_opts(me, me->map_mntopts, 5477c478bd9Sstevel@tonic-gate defaultopts, mapopts)) != PARSE_OK) 5487c478bd9Sstevel@tonic-gate return (rc); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate /* push the options to subdirs */ 5527c478bd9Sstevel@tonic-gate if (node->subdir != NULL) { 5537c478bd9Sstevel@tonic-gate if (node->mapent && strcmp(node->mapent->map_fstype, 5547c478bd9Sstevel@tonic-gate MNTTYPE_AUTOFS) == 0) 5557c478bd9Sstevel@tonic-gate err = MAPENT_UATFS; 5567c478bd9Sstevel@tonic-gate if ((rc = push_options(node->subdir, defaultopts, 5577c478bd9Sstevel@tonic-gate mapopts, err)) != PARSE_OK) 5587c478bd9Sstevel@tonic-gate return (rc); 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate node = node->leveldir; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate return (rc); 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate #define FSTYPE "fstype" 5667c478bd9Sstevel@tonic-gate #define FSTYPE_EQ "fstype=" 5677c478bd9Sstevel@tonic-gate #define NO_OPTS "" 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate /* 5707c478bd9Sstevel@tonic-gate * set_mapent_opts(struct mapent *me, char *opts, char *defaultopts, 5717c478bd9Sstevel@tonic-gate * char *mapopts) 5727c478bd9Sstevel@tonic-gate * sets the mapentry's options, fstype and mounter fields by separating 5737c478bd9Sstevel@tonic-gate * out the fstype part from the opts. Use default options if opts is NULL. 5747c478bd9Sstevel@tonic-gate * Note taht defaultopts may be the same as mapopts. 5757c478bd9Sstevel@tonic-gate * Returns PARSE_OK or appropriate error value. 5767c478bd9Sstevel@tonic-gate */ 5777c478bd9Sstevel@tonic-gate static int 5787c478bd9Sstevel@tonic-gate set_mapent_opts(struct mapent *me, char *opts, char *defaultopts, 5797c478bd9Sstevel@tonic-gate char *mapopts) 5807c478bd9Sstevel@tonic-gate { 5817c478bd9Sstevel@tonic-gate char entryopts[AUTOFS_MAXOPTSLEN]; 5827c478bd9Sstevel@tonic-gate char fstype[MAX_FSLEN], mounter[MAX_FSLEN]; 5837c478bd9Sstevel@tonic-gate int rc = PARSE_OK; 5847c478bd9Sstevel@tonic-gate bool_t fstype_opt = FALSE; 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate strcpy(fstype, MNTTYPE_NFS); /* default */ 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate /* set options to default options, if none exist for this entry */ 5897c478bd9Sstevel@tonic-gate if (opts == NULL) { 5907c478bd9Sstevel@tonic-gate opts = defaultopts; 5917c478bd9Sstevel@tonic-gate if (defaultopts == NULL) { /* NULL opts for entry */ 5927c478bd9Sstevel@tonic-gate strcpy(mounter, fstype); 5937c478bd9Sstevel@tonic-gate goto done; 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate if (*opts == '-') 5977c478bd9Sstevel@tonic-gate opts++; 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate /* separate opts into fstype and (other) entrypopts */ 6007c478bd9Sstevel@tonic-gate get_opts(opts, entryopts, fstype, &fstype_opt); 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate /* replace any existing opts */ 6037c478bd9Sstevel@tonic-gate if (me->map_mntopts != NULL) 6047c478bd9Sstevel@tonic-gate free(me->map_mntopts); 6057c478bd9Sstevel@tonic-gate if ((me->map_mntopts = strdup(entryopts)) == NULL) 6067c478bd9Sstevel@tonic-gate return (ENOMEM); 6077c478bd9Sstevel@tonic-gate strcpy(mounter, fstype); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate /* 6107c478bd9Sstevel@tonic-gate * child options are exactly fstype = somefs, we need to do some 6117c478bd9Sstevel@tonic-gate * more option pushing work. 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate if (fstype_opt == TRUE && 6147c478bd9Sstevel@tonic-gate (strcmp(me->map_mntopts, NO_OPTS) == 0)) { 6157c478bd9Sstevel@tonic-gate free(me->map_mntopts); 6167c478bd9Sstevel@tonic-gate if ((rc = fstype_opts(me, opts, defaultopts, 6177c478bd9Sstevel@tonic-gate mapopts)) != PARSE_OK) 6187c478bd9Sstevel@tonic-gate return (rc); 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate done: 6227c478bd9Sstevel@tonic-gate if (((me->map_fstype = strdup(fstype)) == NULL) || 6237c478bd9Sstevel@tonic-gate ((me->map_mounter = strdup(mounter)) == NULL)) { 6247c478bd9Sstevel@tonic-gate if (me->map_fstype != NULL) 6257c478bd9Sstevel@tonic-gate free(me->map_fstype); 6267c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "set_mapent_opts: No memory"); 6277c478bd9Sstevel@tonic-gate return (ENOMEM); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate return (rc); 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate /* 6347c478bd9Sstevel@tonic-gate * Check the option string for an "fstype" 6357c478bd9Sstevel@tonic-gate * option. If found, return the fstype 6367c478bd9Sstevel@tonic-gate * and the option string with the fstype 6377c478bd9Sstevel@tonic-gate * option removed, e.g. 6387c478bd9Sstevel@tonic-gate * 639*bd93c05dSAlexander Eremin * input: "fstype=nfs,ro,nosuid" 6407c478bd9Sstevel@tonic-gate * opts: "ro,nosuid" 641*bd93c05dSAlexander Eremin * fstype: "nfs" 6427c478bd9Sstevel@tonic-gate * 6437c478bd9Sstevel@tonic-gate * Also indicates if the fstype option was present 6447c478bd9Sstevel@tonic-gate * by setting a flag, if the pointer to the flag 6457c478bd9Sstevel@tonic-gate * is not NULL. 6467c478bd9Sstevel@tonic-gate */ 6477c478bd9Sstevel@tonic-gate static void 6487c478bd9Sstevel@tonic-gate get_opts(input, opts, fstype, fstype_opt) 6497c478bd9Sstevel@tonic-gate char *input; 6507c478bd9Sstevel@tonic-gate char *opts; /* output */ 6517c478bd9Sstevel@tonic-gate char *fstype; /* output */ 6527c478bd9Sstevel@tonic-gate bool_t *fstype_opt; 6537c478bd9Sstevel@tonic-gate { 6547c478bd9Sstevel@tonic-gate char *p, *pb; 6557c478bd9Sstevel@tonic-gate char buf[MAXOPTSLEN]; 6567c478bd9Sstevel@tonic-gate char *placeholder; 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate *opts = '\0'; 6597c478bd9Sstevel@tonic-gate (void) strcpy(buf, input); 6607c478bd9Sstevel@tonic-gate pb = buf; 6617c478bd9Sstevel@tonic-gate while (p = (char *)strtok_r(pb, ",", &placeholder)) { 6627c478bd9Sstevel@tonic-gate pb = NULL; 6637c478bd9Sstevel@tonic-gate if (strncmp(p, FSTYPE_EQ, 7) == 0) { 6647c478bd9Sstevel@tonic-gate if (fstype_opt != NULL) 6657c478bd9Sstevel@tonic-gate *fstype_opt = TRUE; 6667c478bd9Sstevel@tonic-gate (void) strcpy(fstype, p + 7); 6677c478bd9Sstevel@tonic-gate } else { 6687c478bd9Sstevel@tonic-gate if (*opts) 6697c478bd9Sstevel@tonic-gate (void) strcat(opts, ","); 6707c478bd9Sstevel@tonic-gate (void) strcat(opts, p); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate /* 6767c478bd9Sstevel@tonic-gate * fstype_opts(struct mapent *me, char *opts, char *defaultopts, 6777c478bd9Sstevel@tonic-gate * char *mapopts) 6787c478bd9Sstevel@tonic-gate * We need to push global options to the child entry if it is exactly 6797c478bd9Sstevel@tonic-gate * fstype=somefs. 6807c478bd9Sstevel@tonic-gate */ 6817c478bd9Sstevel@tonic-gate static int 6827c478bd9Sstevel@tonic-gate fstype_opts(struct mapent *me, char *opts, char *defaultopts, 6837c478bd9Sstevel@tonic-gate char *mapopts) 6847c478bd9Sstevel@tonic-gate { 6857c478bd9Sstevel@tonic-gate char pushentryopts[AUTOFS_MAXOPTSLEN]; 6867c478bd9Sstevel@tonic-gate char pushfstype[MAX_FSLEN]; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate if (defaultopts && *defaultopts == '-') 6897c478bd9Sstevel@tonic-gate defaultopts++; 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate /* 6927c478bd9Sstevel@tonic-gate * the options to push are the global defaults for the entry, 6937c478bd9Sstevel@tonic-gate * if they exist, or mapopts, if the global defaults for the 6947c478bd9Sstevel@tonic-gate * entry does not exist. 6957c478bd9Sstevel@tonic-gate */ 6967c478bd9Sstevel@tonic-gate if (strcmp(defaultopts, opts) == 0) { 6977c478bd9Sstevel@tonic-gate if (*mapopts == '-') 6987c478bd9Sstevel@tonic-gate mapopts++; 6997c478bd9Sstevel@tonic-gate get_opts(mapopts, pushentryopts, pushfstype, NULL); 7007c478bd9Sstevel@tonic-gate } else { 7017c478bd9Sstevel@tonic-gate get_opts(defaultopts, pushentryopts, pushfstype, NULL); 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate me->map_mntopts = strdup(pushentryopts); 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate if (!me->map_mntopts) { 7077c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "fstype_opts: No memory"); 7087c478bd9Sstevel@tonic-gate return (ENOMEM); 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate return (PARSE_OK); 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate /* 7157c478bd9Sstevel@tonic-gate * modify_mapents(struct mapent **mapents, char *mapname, 7167c478bd9Sstevel@tonic-gate * char *mapopts, char *subdir, hiernode *rootnode, 7177c478bd9Sstevel@tonic-gate * char *key, uint_t isdirect, bool_t mount_access) 7187c478bd9Sstevel@tonic-gate * modifies the intermediate mapentry list into the final one, and passes 7197c478bd9Sstevel@tonic-gate * back a pointer to it. The final list may contain faked mapentries for 7207c478bd9Sstevel@tonic-gate * hiernodes that do not point to a mapentry, or converted mapentries, if 7217c478bd9Sstevel@tonic-gate * hiernodes that point to a mapentry need to be converted from nfs to autofs. 7227c478bd9Sstevel@tonic-gate * mounts. Entries that are not directly 1 level below the subdir are removed. 7237c478bd9Sstevel@tonic-gate * Returns PARSE_OK or PARSE_ERROR 7247c478bd9Sstevel@tonic-gate */ 7257c478bd9Sstevel@tonic-gate static int 7267c478bd9Sstevel@tonic-gate modify_mapents(struct mapent **mapents, char *mapname, 7277c478bd9Sstevel@tonic-gate char *mapopts, char *subdir, hiernode *rootnode, 7287c478bd9Sstevel@tonic-gate char *key, uint_t isdirect, bool_t mount_access) 7297c478bd9Sstevel@tonic-gate { 7307c478bd9Sstevel@tonic-gate struct mapent *mp = NULL; 7317c478bd9Sstevel@tonic-gate char w[MAXPATHLEN]; 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate struct mapent *me; 7347c478bd9Sstevel@tonic-gate int rc = PARSE_OK; 7357c478bd9Sstevel@tonic-gate struct mapent *faked_mapents = NULL; 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate /* 7387c478bd9Sstevel@tonic-gate * correct the mapentry mntlevel from default -1 to level depending on 7397c478bd9Sstevel@tonic-gate * position in hierarchy, and build any faked mapentries, if required 7407c478bd9Sstevel@tonic-gate * at one level below the rootnode given by subdir. 7417c478bd9Sstevel@tonic-gate */ 7427c478bd9Sstevel@tonic-gate if ((rc = set_and_fake_mapent_mntlevel(rootnode, subdir, key, mapname, 7437c478bd9Sstevel@tonic-gate &faked_mapents, isdirect, mapopts, mount_access)) != PARSE_OK) 7447c478bd9Sstevel@tonic-gate return (rc); 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate /* 7477c478bd9Sstevel@tonic-gate * attaches faked mapents to real mapents list. Assumes mapents 7487c478bd9Sstevel@tonic-gate * is not NULL. 7497c478bd9Sstevel@tonic-gate */ 7507c478bd9Sstevel@tonic-gate me = *mapents; 7517c478bd9Sstevel@tonic-gate while (me->map_next != NULL) 7527c478bd9Sstevel@tonic-gate me = me->map_next; 7537c478bd9Sstevel@tonic-gate me->map_next = faked_mapents; 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate /* 7567c478bd9Sstevel@tonic-gate * get rid of nodes marked at level -1 7577c478bd9Sstevel@tonic-gate */ 7587c478bd9Sstevel@tonic-gate me = *mapents; 7597c478bd9Sstevel@tonic-gate while (me != NULL) { 7607c478bd9Sstevel@tonic-gate if ((me->map_mntlevel == -1) || (me->map_err) || 7617c478bd9Sstevel@tonic-gate (mount_access == FALSE && me->map_mntlevel == 0)) { 7627c478bd9Sstevel@tonic-gate /* 7637c478bd9Sstevel@tonic-gate * syslog any errors and free entry 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate if (me->map_err) 7667c478bd9Sstevel@tonic-gate dump_mapent_err(me, key, mapname); 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate if (me == (*mapents)) { 7697c478bd9Sstevel@tonic-gate /* special case when head has to be freed */ 7707c478bd9Sstevel@tonic-gate *mapents = me->map_next; 7717c478bd9Sstevel@tonic-gate if ((*mapents) == NULL) { 7727c478bd9Sstevel@tonic-gate /* something wierd happened */ 7737c478bd9Sstevel@tonic-gate if (verbose) 7747c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 7757c478bd9Sstevel@tonic-gate "modify_mapents: level error"); 7767c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate /* separate out the node */ 7807c478bd9Sstevel@tonic-gate me->map_next = NULL; 7817c478bd9Sstevel@tonic-gate free_mapent(me); 7827c478bd9Sstevel@tonic-gate me = *mapents; 7837c478bd9Sstevel@tonic-gate } else { 7847c478bd9Sstevel@tonic-gate mp->map_next = me->map_next; 7857c478bd9Sstevel@tonic-gate me->map_next = NULL; 7867c478bd9Sstevel@tonic-gate free_mapent(me); 7877c478bd9Sstevel@tonic-gate me = mp->map_next; 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate continue; 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate /* 7937c478bd9Sstevel@tonic-gate * convert level 1 mapents that are not already autonodes 7947c478bd9Sstevel@tonic-gate * to autonodes 7957c478bd9Sstevel@tonic-gate */ 7967c478bd9Sstevel@tonic-gate if (me->map_mntlevel == 1 && 7977c478bd9Sstevel@tonic-gate (strcmp(me->map_fstype, MNTTYPE_AUTOFS) != 0) && 7987c478bd9Sstevel@tonic-gate (me->map_faked != TRUE)) { 7997c478bd9Sstevel@tonic-gate if ((rc = convert_mapent_to_automount(me, mapname, 8007c478bd9Sstevel@tonic-gate mapopts)) != PARSE_OK) 8017c478bd9Sstevel@tonic-gate return (rc); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate strcpy(w, (me->map_mntpnt+strlen(subdir))); 8047c478bd9Sstevel@tonic-gate strcpy(me->map_mntpnt, w); 8057c478bd9Sstevel@tonic-gate mp = me; 8067c478bd9Sstevel@tonic-gate me = me->map_next; 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate if (trace > 3) 8107c478bd9Sstevel@tonic-gate trace_mapents("modify_mapents:", *mapents); 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate return (PARSE_OK); 8137c478bd9Sstevel@tonic-gate } 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate /* 8167c478bd9Sstevel@tonic-gate * set_and_fake_mapent_mntlevel(hiernode *rootnode, char *subdir, char *key, 8177c478bd9Sstevel@tonic-gate * char *mapname, struct mapent **faked_mapents, 8187c478bd9Sstevel@tonic-gate * uint_t isdirect, char *mapopts, bool_t mount_access) 8197c478bd9Sstevel@tonic-gate * sets the mapentry mount levels (depths) with respect to the subdir. 8207c478bd9Sstevel@tonic-gate * Assigns a value of 0 to the new root. Finds the level1 directories by 8217c478bd9Sstevel@tonic-gate * calling mark_*_level1_*(). Also cleans off extra /'s in level0 and 8227c478bd9Sstevel@tonic-gate * level1 map_mntpnts. Note that one level below the new root is an existing 8237c478bd9Sstevel@tonic-gate * mapentry if there's a mapentry (nfs mount) corresponding to the root, 8247c478bd9Sstevel@tonic-gate * and the direct subdir set for the root, if there's no mapentry corresponding 8257c478bd9Sstevel@tonic-gate * to the root (we install autodirs). Returns PARSE_OK or error value. 8267c478bd9Sstevel@tonic-gate */ 8277c478bd9Sstevel@tonic-gate static int 8287c478bd9Sstevel@tonic-gate set_and_fake_mapent_mntlevel(hiernode *rootnode, char *subdir, char *key, 8297c478bd9Sstevel@tonic-gate char *mapname, struct mapent **faked_mapents, 8307c478bd9Sstevel@tonic-gate uint_t isdirect, char *mapopts, bool_t mount_access) 8317c478bd9Sstevel@tonic-gate { 8327c478bd9Sstevel@tonic-gate char dirname[MAXFILENAMELEN]; 8337c478bd9Sstevel@tonic-gate char traversed_path[MAXPATHLEN]; /* used in building fake mapentries */ 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate char *subdir_child = subdir; 8367c478bd9Sstevel@tonic-gate hiernode *prevnode = rootnode; 8377c478bd9Sstevel@tonic-gate hiernode *currnode = rootnode->subdir; 8387c478bd9Sstevel@tonic-gate int rc = PARSE_OK; 8397c478bd9Sstevel@tonic-gate traversed_path[0] = '\0'; 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate /* 8427c478bd9Sstevel@tonic-gate * find and mark the root by tracing down subdir. Use traversed_path 8437c478bd9Sstevel@tonic-gate * to keep track of how far we go, while guaranteeing that it 8447c478bd9Sstevel@tonic-gate * contains no '/' at the end. Took some mucking to get that right. 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate if ((rc = get_dir_from_path(dirname, &subdir_child, sizeof (dirname))) 8477c478bd9Sstevel@tonic-gate != PARSE_OK) 8487c478bd9Sstevel@tonic-gate return (rc); 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate if (dirname[0] != '\0') 8517c478bd9Sstevel@tonic-gate sprintf(traversed_path, "%s/%s", traversed_path, dirname); 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate prevnode = rootnode; 8547c478bd9Sstevel@tonic-gate currnode = rootnode->subdir; 8557c478bd9Sstevel@tonic-gate while (dirname[0] != '\0' && currnode != NULL) { 8567c478bd9Sstevel@tonic-gate if (strcmp(currnode->dirname, dirname) == 0) { 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate /* subdir is a child of currnode */ 8597c478bd9Sstevel@tonic-gate prevnode = currnode; 8607c478bd9Sstevel@tonic-gate currnode = currnode->subdir; 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate if ((rc = get_dir_from_path(dirname, &subdir_child, 8637c478bd9Sstevel@tonic-gate sizeof (dirname))) != PARSE_OK) 8647c478bd9Sstevel@tonic-gate return (rc); 8657c478bd9Sstevel@tonic-gate if (dirname[0] != '\0') 8667c478bd9Sstevel@tonic-gate sprintf(traversed_path, "%s/%s", 8677c478bd9Sstevel@tonic-gate traversed_path, dirname); 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate } else { 8707c478bd9Sstevel@tonic-gate /* try next leveldir */ 8717c478bd9Sstevel@tonic-gate prevnode = currnode; 8727c478bd9Sstevel@tonic-gate currnode = currnode->leveldir; 8737c478bd9Sstevel@tonic-gate } 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate if (dirname[0] != '\0') { 8777c478bd9Sstevel@tonic-gate if (verbose) 8787c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 8797c478bd9Sstevel@tonic-gate "set_and_fake_mapent_mntlevel: subdir=%s error: map=%s", 8807c478bd9Sstevel@tonic-gate subdir, mapname); 8817c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 8827c478bd9Sstevel@tonic-gate } 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate /* 8857c478bd9Sstevel@tonic-gate * see if level of root really points to a mapent and if 8867c478bd9Sstevel@tonic-gate * have access to that filessystem - call appropriate 8877c478bd9Sstevel@tonic-gate * routine to mark level 1 nodes, and build faked entries 8887c478bd9Sstevel@tonic-gate */ 8897c478bd9Sstevel@tonic-gate if (prevnode->mapent != NULL && mount_access == TRUE) { 8907c478bd9Sstevel@tonic-gate if (trace > 3) 8917c478bd9Sstevel@tonic-gate trace_prt(1, " node mountpoint %s\t travpath=%s\n", 8927c478bd9Sstevel@tonic-gate prevnode->mapent->map_mntpnt, traversed_path); 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate /* 8957c478bd9Sstevel@tonic-gate * Copy traversed path map_mntpnt to get rid of any extra 8967c478bd9Sstevel@tonic-gate * '/' the map entry may contain. 8977c478bd9Sstevel@tonic-gate */ 8987c478bd9Sstevel@tonic-gate if (strlen(prevnode->mapent->map_mntpnt) < 8997c478bd9Sstevel@tonic-gate strlen(traversed_path)) { /* sanity check */ 9007c478bd9Sstevel@tonic-gate if (verbose) 9017c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 9027c478bd9Sstevel@tonic-gate "set_and_fake_mapent_mntlevel: path=%s error", 9037c478bd9Sstevel@tonic-gate traversed_path); 9047c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate if (strcmp(prevnode->mapent->map_mntpnt, traversed_path) != 0) 9077c478bd9Sstevel@tonic-gate strcpy(prevnode->mapent->map_mntpnt, traversed_path); 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate prevnode->mapent->map_mntlevel = 0; /* root level is 0 */ 9107c478bd9Sstevel@tonic-gate if (currnode != NULL) { 9117c478bd9Sstevel@tonic-gate if ((rc = mark_level1_root(currnode, 9127c478bd9Sstevel@tonic-gate traversed_path)) != PARSE_OK) 9137c478bd9Sstevel@tonic-gate return (rc); 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate } else if (currnode != NULL) { 9167c478bd9Sstevel@tonic-gate if (trace > 3) 9177c478bd9Sstevel@tonic-gate trace_prt(1, " No rootnode, travpath=%s\n", 9187c478bd9Sstevel@tonic-gate traversed_path); 9197c478bd9Sstevel@tonic-gate if ((rc = mark_and_fake_level1_noroot(currnode, 9207c478bd9Sstevel@tonic-gate traversed_path, key, mapname, faked_mapents, isdirect, 9217c478bd9Sstevel@tonic-gate mapopts)) != PARSE_OK) 9227c478bd9Sstevel@tonic-gate return (rc); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate if (trace > 3) { 9267c478bd9Sstevel@tonic-gate trace_prt(1, "\n\tset_and_fake_mapent_mntlevel\n"); 9277c478bd9Sstevel@tonic-gate trace_hierarchy(rootnode, 0); 9287c478bd9Sstevel@tonic-gate } 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate return (rc); 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate /* 9357c478bd9Sstevel@tonic-gate * mark_level1_root(hiernode *node, char *traversed_path) 9367c478bd9Sstevel@tonic-gate * marks nodes upto one level below the rootnode given by subdir 9377c478bd9Sstevel@tonic-gate * recursively. Called if rootnode points to a mapent. 9387c478bd9Sstevel@tonic-gate * In this routine, a level 1 node is considered to be the 1st existing 9397c478bd9Sstevel@tonic-gate * mapentry below the root node, so there's no faking involved. 9407c478bd9Sstevel@tonic-gate * Returns PARSE_OK or error value 9417c478bd9Sstevel@tonic-gate */ 9427c478bd9Sstevel@tonic-gate static int 9437c478bd9Sstevel@tonic-gate mark_level1_root(hiernode *node, char *traversed_path) 9447c478bd9Sstevel@tonic-gate { 9457c478bd9Sstevel@tonic-gate /* ensure we touch all leveldirs */ 9467c478bd9Sstevel@tonic-gate while (node) { 9477c478bd9Sstevel@tonic-gate /* 9487c478bd9Sstevel@tonic-gate * mark node level as 1, if one exists - else walk down 9497c478bd9Sstevel@tonic-gate * subdirs until we find one. 9507c478bd9Sstevel@tonic-gate */ 9517c478bd9Sstevel@tonic-gate if (node->mapent == NULL) { 9527c478bd9Sstevel@tonic-gate char w[MAXPATHLEN]; 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate if (node->subdir != NULL) { 9557c478bd9Sstevel@tonic-gate sprintf(w, "%s/%s", traversed_path, 9567c478bd9Sstevel@tonic-gate node->dirname); 9577c478bd9Sstevel@tonic-gate if (mark_level1_root(node->subdir, w) 9587c478bd9Sstevel@tonic-gate == PARSE_ERROR) 9597c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 9607c478bd9Sstevel@tonic-gate } else { 9617c478bd9Sstevel@tonic-gate if (verbose) { 9627c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 9637c478bd9Sstevel@tonic-gate "mark_level1_root: hierarchy error"); 9647c478bd9Sstevel@tonic-gate } 9657c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate } else { 9687c478bd9Sstevel@tonic-gate char w[MAXPATHLEN]; 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate sprintf(w, "%s/%s", traversed_path, node->dirname); 9717c478bd9Sstevel@tonic-gate if (trace > 3) 9727c478bd9Sstevel@tonic-gate trace_prt(1, " node mntpnt %s\t travpath %s\n", 9737c478bd9Sstevel@tonic-gate node->mapent->map_mntpnt, w); 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate /* replace mntpnt with travpath to clean extra '/' */ 9767c478bd9Sstevel@tonic-gate if (strlen(node->mapent->map_mntpnt) < strlen(w)) { 9777c478bd9Sstevel@tonic-gate if (verbose) { 9787c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 9797c478bd9Sstevel@tonic-gate "mark_level1_root: path=%s error", 9807c478bd9Sstevel@tonic-gate traversed_path); 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate if (strcmp(node->mapent->map_mntpnt, w) != 0) 9857c478bd9Sstevel@tonic-gate strcpy(node->mapent->map_mntpnt, w); 9867c478bd9Sstevel@tonic-gate node->mapent->map_mntlevel = 1; 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate node = node->leveldir; 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate return (PARSE_OK); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate /* 9947c478bd9Sstevel@tonic-gate * mark_and_fake_level1_noroot(hiernode *node, char *traversed_path, 9957c478bd9Sstevel@tonic-gate * char *key,char *mapname, struct mapent **faked_mapents, 9967c478bd9Sstevel@tonic-gate * uint_t isdirect, char *mapopts) 9977c478bd9Sstevel@tonic-gate * Called if the root of the hierarchy does not point to a mapent. marks nodes 9987c478bd9Sstevel@tonic-gate * upto one physical level below the rootnode given by subdir. checks if 9997c478bd9Sstevel@tonic-gate * there's a real mapentry. If not, it builds a faked one (autonode) at that 10007c478bd9Sstevel@tonic-gate * point. The faked autonode is direct, with the map being the same as the 10017c478bd9Sstevel@tonic-gate * original one from which the call originated. Options are same as that of 10027c478bd9Sstevel@tonic-gate * the map and assigned in automount_opts(). Returns PARSE_OK or error value. 10037c478bd9Sstevel@tonic-gate */ 10047c478bd9Sstevel@tonic-gate static int 10057c478bd9Sstevel@tonic-gate mark_and_fake_level1_noroot(hiernode *node, char *traversed_path, 10067c478bd9Sstevel@tonic-gate char *key, char *mapname, struct mapent **faked_mapents, 10077c478bd9Sstevel@tonic-gate uint_t isdirect, char *mapopts) 10087c478bd9Sstevel@tonic-gate { 10097c478bd9Sstevel@tonic-gate struct mapent *me; 10107c478bd9Sstevel@tonic-gate int rc = 0; 10117c478bd9Sstevel@tonic-gate char faked_map_mntpnt[MAXPATHLEN]; 10127c478bd9Sstevel@tonic-gate char w1[MAXPATHLEN]; 10137c478bd9Sstevel@tonic-gate char w[MAXPATHLEN]; 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate while (node != NULL) { 10167c478bd9Sstevel@tonic-gate if (node->mapent != NULL) { 10177c478bd9Sstevel@tonic-gate /* 10187c478bd9Sstevel@tonic-gate * existing mapentry at level 1 - copy travpath to 10197c478bd9Sstevel@tonic-gate * get rid of extra '/' in mntpnt 10207c478bd9Sstevel@tonic-gate */ 10217c478bd9Sstevel@tonic-gate sprintf(w, "%s/%s", traversed_path, node->dirname); 10227c478bd9Sstevel@tonic-gate if (trace > 3) 10237c478bd9Sstevel@tonic-gate trace_prt(1, " node mntpnt=%s\t travpath=%s\n", 10247c478bd9Sstevel@tonic-gate node->mapent->map_mntpnt, w); 10257c478bd9Sstevel@tonic-gate if (strlen(node->mapent->map_mntpnt) < strlen(w)) { 10267c478bd9Sstevel@tonic-gate /* sanity check */ 10277c478bd9Sstevel@tonic-gate if (verbose) 10287c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 10297c478bd9Sstevel@tonic-gate "mark_fake_level1_noroot:path=%s error", 10307c478bd9Sstevel@tonic-gate traversed_path); 10317c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 10327c478bd9Sstevel@tonic-gate } 10337c478bd9Sstevel@tonic-gate if (strcmp(node->mapent->map_mntpnt, w) != 0) 10347c478bd9Sstevel@tonic-gate strcpy(node->mapent->map_mntpnt, w); 10357c478bd9Sstevel@tonic-gate node->mapent->map_mntlevel = 1; 10367c478bd9Sstevel@tonic-gate } else { 10377c478bd9Sstevel@tonic-gate /* 10387c478bd9Sstevel@tonic-gate * build the faked autonode 10397c478bd9Sstevel@tonic-gate */ 10407c478bd9Sstevel@tonic-gate if ((me = (struct mapent *)malloc(sizeof (*me))) 10417c478bd9Sstevel@tonic-gate == NULL) { 10427c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 10437c478bd9Sstevel@tonic-gate "mark_and_fake_level1_noroot: out of memory"); 10447c478bd9Sstevel@tonic-gate return (ENOMEM); 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate (void) memset((char *)me, 0, sizeof (*me)); 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate if ((me->map_fs = (struct mapfs *) 10497c478bd9Sstevel@tonic-gate malloc(sizeof (struct mapfs))) == NULL) 10507c478bd9Sstevel@tonic-gate return (ENOMEM); 10517c478bd9Sstevel@tonic-gate (void) memset(me->map_fs, 0, sizeof (struct mapfs)); 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate if (isdirect) { 10547c478bd9Sstevel@tonic-gate *w1 = '\0'; 10557c478bd9Sstevel@tonic-gate } else { 10567c478bd9Sstevel@tonic-gate strcpy(w1, "/"); 10577c478bd9Sstevel@tonic-gate strcat(w1, key); 10587c478bd9Sstevel@tonic-gate } 10597c478bd9Sstevel@tonic-gate me->map_root = strdup(w1); 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate sprintf(faked_map_mntpnt, "%s/%s", traversed_path, 10627c478bd9Sstevel@tonic-gate node->dirname); 10637c478bd9Sstevel@tonic-gate me->map_mntpnt = strdup(faked_map_mntpnt); 10647c478bd9Sstevel@tonic-gate me->map_fstype = strdup(MNTTYPE_AUTOFS); 10657c478bd9Sstevel@tonic-gate me->map_mounter = strdup(MNTTYPE_AUTOFS); 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate /* set options */ 10687c478bd9Sstevel@tonic-gate if ((rc = automount_opts(&me->map_mntopts, mapopts)) 10697c478bd9Sstevel@tonic-gate != PARSE_OK) 10707c478bd9Sstevel@tonic-gate return (rc); 10717c478bd9Sstevel@tonic-gate me->map_fs->mfs_dir = strdup(mapname); 10727c478bd9Sstevel@tonic-gate me->map_mntlevel = 1; 10737c478bd9Sstevel@tonic-gate me->map_modified = FALSE; 10747c478bd9Sstevel@tonic-gate me->map_faked = TRUE; /* mark as faked */ 10757c478bd9Sstevel@tonic-gate if (me->map_root == NULL || 10767c478bd9Sstevel@tonic-gate me->map_mntpnt == NULL || 10777c478bd9Sstevel@tonic-gate me->map_fstype == NULL || 10787c478bd9Sstevel@tonic-gate me->map_mounter == NULL || 10797c478bd9Sstevel@tonic-gate me->map_mntopts == NULL || 10807c478bd9Sstevel@tonic-gate me->map_fs->mfs_dir == NULL) { 10817c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 10827c478bd9Sstevel@tonic-gate "mark_and_fake_level1_noroot: out of memory"); 10837c478bd9Sstevel@tonic-gate free_mapent(*faked_mapents); 10847c478bd9Sstevel@tonic-gate return (ENOMEM); 10857c478bd9Sstevel@tonic-gate } 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate if (*faked_mapents == NULL) 10887c478bd9Sstevel@tonic-gate *faked_mapents = me; 10897c478bd9Sstevel@tonic-gate else { /* attach to the head */ 10907c478bd9Sstevel@tonic-gate me->map_next = *faked_mapents; 10917c478bd9Sstevel@tonic-gate *faked_mapents = me; 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate node->mapent = me; 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate node = node->leveldir; 10967c478bd9Sstevel@tonic-gate } 10977c478bd9Sstevel@tonic-gate return (rc); 10987c478bd9Sstevel@tonic-gate } 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate /* 11017c478bd9Sstevel@tonic-gate * convert_mapent_to_automount(struct mapent *me, char *mapname, 11027c478bd9Sstevel@tonic-gate * char *mapopts) 11037c478bd9Sstevel@tonic-gate * change the mapentry me to an automount - free fields first and NULL them 11047c478bd9Sstevel@tonic-gate * to avoid freeing again, while freeing the mapentry at a later stage. 11057c478bd9Sstevel@tonic-gate * Could have avoided freeing entries here as we don't really look at them. 11067c478bd9Sstevel@tonic-gate * Give the converted mapent entry the options that came with the map using 11077c478bd9Sstevel@tonic-gate * automount_opts(). Returns PARSE_OK or appropriate error value. 11087c478bd9Sstevel@tonic-gate */ 11097c478bd9Sstevel@tonic-gate static int 11107c478bd9Sstevel@tonic-gate convert_mapent_to_automount(struct mapent *me, char *mapname, 11117c478bd9Sstevel@tonic-gate char *mapopts) 11127c478bd9Sstevel@tonic-gate { 11137c478bd9Sstevel@tonic-gate struct mapfs *mfs = me->map_fs; /* assumes it exists */ 11147c478bd9Sstevel@tonic-gate int rc = PARSE_OK; 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate /* free relevant entries */ 11177c478bd9Sstevel@tonic-gate if (mfs->mfs_host) { 11187c478bd9Sstevel@tonic-gate free(mfs->mfs_host); 11197c478bd9Sstevel@tonic-gate mfs->mfs_host = NULL; 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate while (me->map_fs->mfs_next != NULL) { 11227c478bd9Sstevel@tonic-gate mfs = me->map_fs->mfs_next; 11237c478bd9Sstevel@tonic-gate if (mfs->mfs_host) 11247c478bd9Sstevel@tonic-gate free(mfs->mfs_host); 11257c478bd9Sstevel@tonic-gate if (mfs->mfs_dir) 11267c478bd9Sstevel@tonic-gate free(mfs->mfs_dir); 11277c478bd9Sstevel@tonic-gate me->map_fs->mfs_next = mfs->mfs_next; /* nulls eventually */ 11287c478bd9Sstevel@tonic-gate free((void*)mfs); 11297c478bd9Sstevel@tonic-gate } 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate /* replace relevant entries */ 11327c478bd9Sstevel@tonic-gate if (me->map_fstype) 11337c478bd9Sstevel@tonic-gate free(me->map_fstype); 11347c478bd9Sstevel@tonic-gate if ((me->map_fstype = strdup(MNTTYPE_AUTOFS)) == NULL) 11357c478bd9Sstevel@tonic-gate goto alloc_failed; 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate if (me->map_mounter) 11387c478bd9Sstevel@tonic-gate free(me->map_mounter); 11397c478bd9Sstevel@tonic-gate if ((me->map_mounter = strdup(me->map_fstype)) == NULL) 11407c478bd9Sstevel@tonic-gate goto alloc_failed; 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate if (me->map_fs->mfs_dir) 11437c478bd9Sstevel@tonic-gate free(me->map_fs->mfs_dir); 11447c478bd9Sstevel@tonic-gate if ((me->map_fs->mfs_dir = strdup(mapname)) == NULL) 11457c478bd9Sstevel@tonic-gate goto alloc_failed; 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate /* set options */ 11487c478bd9Sstevel@tonic-gate if (me->map_mntopts) 11497c478bd9Sstevel@tonic-gate free(me->map_mntopts); 11507c478bd9Sstevel@tonic-gate if ((rc = automount_opts(&me->map_mntopts, mapopts)) != PARSE_OK) 11517c478bd9Sstevel@tonic-gate return (rc); 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate /* mucked with this entry, set the map_modified field to TRUE */ 11547c478bd9Sstevel@tonic-gate me->map_modified = TRUE; 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate return (rc); 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate alloc_failed: 11597c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 11607c478bd9Sstevel@tonic-gate "convert_mapent_to_automount: Memory allocation failed"); 11617c478bd9Sstevel@tonic-gate return (ENOMEM); 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate /* 11657c478bd9Sstevel@tonic-gate * automount_opts(char **map_mntopts, char *mapopts) 11667c478bd9Sstevel@tonic-gate * modifies automount opts - gets rid of all "indirect" and "direct" strings 11677c478bd9Sstevel@tonic-gate * if they exist, and then adds a direct string to force a direct automount. 11687c478bd9Sstevel@tonic-gate * Rest of the mapopts stay intact. Returns PARSE_OK or appropriate error. 11697c478bd9Sstevel@tonic-gate */ 11707c478bd9Sstevel@tonic-gate static int 11717c478bd9Sstevel@tonic-gate automount_opts(char **map_mntopts, char *mapopts) 11727c478bd9Sstevel@tonic-gate { 11737c478bd9Sstevel@tonic-gate char *opts; 11747c478bd9Sstevel@tonic-gate char *opt; 11757c478bd9Sstevel@tonic-gate int len; 11767c478bd9Sstevel@tonic-gate char *placeholder; 11777c478bd9Sstevel@tonic-gate char buf[AUTOFS_MAXOPTSLEN]; 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate char *addopt = "direct"; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate len = strlen(mapopts)+ strlen(addopt)+2; /* +2 for ",", '\0' */ 11827c478bd9Sstevel@tonic-gate if (len > AUTOFS_MAXOPTSLEN) { 11837c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 11847c478bd9Sstevel@tonic-gate "option string %s too long (max=%d)", mapopts, 11857c478bd9Sstevel@tonic-gate AUTOFS_MAXOPTSLEN-8); 11867c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 11877c478bd9Sstevel@tonic-gate } 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate if (((*map_mntopts) = ((char *)malloc(len))) == NULL) { 11907c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "automount_opts: Memory allocation failed"); 11917c478bd9Sstevel@tonic-gate return (ENOMEM); 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate memset(*map_mntopts, 0, len); 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate strcpy(buf, mapopts); 11967c478bd9Sstevel@tonic-gate opts = buf; 11977c478bd9Sstevel@tonic-gate while ((opt = strtok_r(opts, ",", &placeholder)) != NULL) { 11987c478bd9Sstevel@tonic-gate opts = NULL; 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate /* remove trailing and leading spaces */ 12017c478bd9Sstevel@tonic-gate while (isspace(*opt)) 12027c478bd9Sstevel@tonic-gate opt++; 12037c478bd9Sstevel@tonic-gate len = strlen(opt)-1; 12047c478bd9Sstevel@tonic-gate while (isspace(opt[len])) 12057c478bd9Sstevel@tonic-gate opt[len--] = '\0'; 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate /* 12087c478bd9Sstevel@tonic-gate * if direct or indirect found, get rid of it, else put it 12097c478bd9Sstevel@tonic-gate * back 12107c478bd9Sstevel@tonic-gate */ 12117c478bd9Sstevel@tonic-gate if ((strcmp(opt, "indirect") == 0) || 12127c478bd9Sstevel@tonic-gate (strcmp(opt, "direct") == 0)) 12137c478bd9Sstevel@tonic-gate continue; 12147c478bd9Sstevel@tonic-gate if (*map_mntopts[0] != '\0') 12157c478bd9Sstevel@tonic-gate strcat(*map_mntopts, ","); 12167c478bd9Sstevel@tonic-gate strcat(*map_mntopts, opt); 12177c478bd9Sstevel@tonic-gate } 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate /* add the direct string at the end */ 12207c478bd9Sstevel@tonic-gate if (*map_mntopts[0] != '\0') 12217c478bd9Sstevel@tonic-gate strcat(*map_mntopts, ","); 12227c478bd9Sstevel@tonic-gate strcat(*map_mntopts, addopt); 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate return (PARSE_OK); 12257c478bd9Sstevel@tonic-gate } 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate /* 12287c478bd9Sstevel@tonic-gate * parse_fsinfo(char *mapname, struct mapent *mapents) 12297c478bd9Sstevel@tonic-gate * parses the filesystem information stored in me->map_fsw and me->map_fswq 12307c478bd9Sstevel@tonic-gate * and calls appropriate filesystem parser. 12317c478bd9Sstevel@tonic-gate * Returns PARSE_OK or an appropriate error value. 12327c478bd9Sstevel@tonic-gate */ 12337c478bd9Sstevel@tonic-gate static int 12347c478bd9Sstevel@tonic-gate parse_fsinfo(char *mapname, struct mapent *mapents) 12357c478bd9Sstevel@tonic-gate { 12367c478bd9Sstevel@tonic-gate struct mapent *me = mapents; 12377c478bd9Sstevel@tonic-gate char *bufp; 12387c478bd9Sstevel@tonic-gate char *bufq; 12397c478bd9Sstevel@tonic-gate int wordsz = MAXPATHLEN; 12407c478bd9Sstevel@tonic-gate int err = 0; 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate while (me != NULL) { 12437c478bd9Sstevel@tonic-gate bufp = ""; 12447c478bd9Sstevel@tonic-gate bufq = ""; 12457c478bd9Sstevel@tonic-gate if (strcmp(me->map_fstype, MNTTYPE_NFS) == 0) { 12467c478bd9Sstevel@tonic-gate err = parse_nfs(mapname, me, me->map_fsw, 12477c478bd9Sstevel@tonic-gate me->map_fswq, &bufp, &bufq, wordsz); 12487c478bd9Sstevel@tonic-gate } else { 12497c478bd9Sstevel@tonic-gate err = parse_special(me, me->map_fsw, me->map_fswq, 12507c478bd9Sstevel@tonic-gate &bufp, &bufq, wordsz); 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate if (err != PARSE_OK || *me->map_fsw != '\0' || 12547c478bd9Sstevel@tonic-gate *me->map_fswq != '\0') { 12557c478bd9Sstevel@tonic-gate /* sanity check */ 12567c478bd9Sstevel@tonic-gate if (verbose) 12577c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 12587c478bd9Sstevel@tonic-gate "parse_fsinfo: mount location error %s", 12597c478bd9Sstevel@tonic-gate me->map_fsw); 12607c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 12617c478bd9Sstevel@tonic-gate } 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate me = me->map_next; 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate 12667c478bd9Sstevel@tonic-gate if (trace > 3) { 12677c478bd9Sstevel@tonic-gate trace_mapents("parse_fsinfo:", mapents); 12687c478bd9Sstevel@tonic-gate } 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate return (PARSE_OK); 12717c478bd9Sstevel@tonic-gate } 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate /* 12747c478bd9Sstevel@tonic-gate * This function parses the map entry for a nfs type file system 12757c478bd9Sstevel@tonic-gate * The input is the string lp (and lq) which can be one of the 12767c478bd9Sstevel@tonic-gate * following forms: 12777c478bd9Sstevel@tonic-gate * a) host[(penalty)][,host[(penalty)]]... :/directory 12787c478bd9Sstevel@tonic-gate * b) host[(penalty)]:/directory[ host[(penalty)]:/directory]... 12797c478bd9Sstevel@tonic-gate * This routine constructs a mapfs link-list for each of 12807c478bd9Sstevel@tonic-gate * the hosts and the corresponding file system. The list 12817c478bd9Sstevel@tonic-gate * is then attatched to the mapent struct passed in. 12827c478bd9Sstevel@tonic-gate */ 128311606941Sjwahlig int 12847c478bd9Sstevel@tonic-gate parse_nfs(mapname, me, fsw, fswq, lp, lq, wsize) 12857c478bd9Sstevel@tonic-gate struct mapent *me; 12867c478bd9Sstevel@tonic-gate char *mapname, *fsw, *fswq, **lp, **lq; 12877c478bd9Sstevel@tonic-gate int wsize; 12887c478bd9Sstevel@tonic-gate { 12897c478bd9Sstevel@tonic-gate struct mapfs *mfs, **mfsp; 12907c478bd9Sstevel@tonic-gate char *wlp, *wlq; 12917c478bd9Sstevel@tonic-gate char *hl, hostlist[1024], *hlq, hostlistq[1024]; 12927c478bd9Sstevel@tonic-gate char hostname_and_penalty[MXHOSTNAMELEN+5]; 12937c478bd9Sstevel@tonic-gate char *hn, *hnq, hostname[MXHOSTNAMELEN+1]; 12947c478bd9Sstevel@tonic-gate char dirname[MAXPATHLEN+1], subdir[MAXPATHLEN+1]; 12957c478bd9Sstevel@tonic-gate char qbuff[MAXPATHLEN+1], qbuff1[MAXPATHLEN+1]; 12967c478bd9Sstevel@tonic-gate char pbuff[10], pbuffq[10]; 12977c478bd9Sstevel@tonic-gate int penalty; 12987c478bd9Sstevel@tonic-gate char w[MAXPATHLEN]; 12997c478bd9Sstevel@tonic-gate char wq[MAXPATHLEN]; 13007c478bd9Sstevel@tonic-gate int host_cnt; 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate mfsp = &me->map_fs; 13037c478bd9Sstevel@tonic-gate *mfsp = NULL; 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate /* 13067c478bd9Sstevel@tonic-gate * there may be more than one entry in the map list. Get the 13077c478bd9Sstevel@tonic-gate * first one. Use temps to handle the word information and 13087c478bd9Sstevel@tonic-gate * copy back into fsw and fswq fields when done. 13097c478bd9Sstevel@tonic-gate */ 13107c478bd9Sstevel@tonic-gate *lp = fsw; 13117c478bd9Sstevel@tonic-gate *lq = fswq; 13127c478bd9Sstevel@tonic-gate if (getword(w, wq, lp, lq, ' ', wsize) == -1) 13137c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 13147c478bd9Sstevel@tonic-gate while (*w && *w != '/') { 13157c478bd9Sstevel@tonic-gate bool_t maybe_url; 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate maybe_url = TRUE; 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate wlp = w; wlq = wq; 13207c478bd9Sstevel@tonic-gate if (getword(hostlist, hostlistq, &wlp, &wlq, ':', 13217c478bd9Sstevel@tonic-gate sizeof (hostlist)) == -1) 13227c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 13237c478bd9Sstevel@tonic-gate if (!*hostlist) 13247c478bd9Sstevel@tonic-gate goto bad_entry; 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate if (strcmp(hostlist, "nfs") != 0) 13277c478bd9Sstevel@tonic-gate maybe_url = FALSE; 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate if (getword(dirname, qbuff, &wlp, &wlq, ':', 13307c478bd9Sstevel@tonic-gate sizeof (dirname)) == -1) 13317c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 13327c478bd9Sstevel@tonic-gate if (*dirname == '\0') 13337c478bd9Sstevel@tonic-gate goto bad_entry; 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate if (maybe_url == TRUE && strncmp(dirname, "//", 2) != 0) 13367c478bd9Sstevel@tonic-gate maybe_url = FALSE; 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate /* 13397c478bd9Sstevel@tonic-gate * See the next block comment ("Once upon a time ...") to 13407c478bd9Sstevel@tonic-gate * understand this. It turns the deprecated concept 13417c478bd9Sstevel@tonic-gate * of "subdir mounts" produced some useful code for handling 13427c478bd9Sstevel@tonic-gate * the possibility of a ":port#" in the URL. 13437c478bd9Sstevel@tonic-gate */ 13447c478bd9Sstevel@tonic-gate if (maybe_url == FALSE) 13457c478bd9Sstevel@tonic-gate *subdir = '/'; 13467c478bd9Sstevel@tonic-gate else 13477c478bd9Sstevel@tonic-gate *subdir = ':'; 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate *qbuff = ' '; 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate /* 13527c478bd9Sstevel@tonic-gate * Once upon time, before autofs, there was support for 13537c478bd9Sstevel@tonic-gate * "subdir mounts". The idea was to "economize" the 13547c478bd9Sstevel@tonic-gate * number of mounts, so if you had a number of entries 13557c478bd9Sstevel@tonic-gate * all referring to a common subdirectory, e.g. 13567c478bd9Sstevel@tonic-gate * 13577c478bd9Sstevel@tonic-gate * carol seasons:/export/home11/carol 13587c478bd9Sstevel@tonic-gate * ted seasons:/export/home11/ted 13597c478bd9Sstevel@tonic-gate * alice seasons:/export/home11/alice 13607c478bd9Sstevel@tonic-gate * 13617c478bd9Sstevel@tonic-gate * then you could tell the automounter to mount a 13627c478bd9Sstevel@tonic-gate * common mountpoint which was delimited by the second 13637c478bd9Sstevel@tonic-gate * colon: 13647c478bd9Sstevel@tonic-gate * 13657c478bd9Sstevel@tonic-gate * carol seasons:/export/home11:carol 13667c478bd9Sstevel@tonic-gate * ted seasons:/export/home11:ted 13677c478bd9Sstevel@tonic-gate * alice seasons:/export/home11:alice 13687c478bd9Sstevel@tonic-gate * 13697c478bd9Sstevel@tonic-gate * The automounter would mount seasons:/export/home11 13707c478bd9Sstevel@tonic-gate * then for any other map entry that referenced the same 13717c478bd9Sstevel@tonic-gate * directory it would build a symbolic link that 13727c478bd9Sstevel@tonic-gate * appended the remainder of the path after the second 13737c478bd9Sstevel@tonic-gate * colon, i.e. once the common subdir was mounted, then 13747c478bd9Sstevel@tonic-gate * other directories could be accessed just by link 13757c478bd9Sstevel@tonic-gate * building - no further mounts required. 13767c478bd9Sstevel@tonic-gate * 13777c478bd9Sstevel@tonic-gate * In theory the "mount saving" idea sounded good. In 13787c478bd9Sstevel@tonic-gate * practice the saving didn't amount to much and the 13797c478bd9Sstevel@tonic-gate * symbolic links confused people because the common 13807c478bd9Sstevel@tonic-gate * mountpoint had to have a pseudonym. 13817c478bd9Sstevel@tonic-gate * 13827c478bd9Sstevel@tonic-gate * To remain backward compatible with the existing 13837c478bd9Sstevel@tonic-gate * maps, we interpret a second colon as a slash. 13847c478bd9Sstevel@tonic-gate */ 13857c478bd9Sstevel@tonic-gate if (getword(subdir+1, qbuff+1, &wlp, &wlq, ':', 13867c478bd9Sstevel@tonic-gate sizeof (subdir)) == -1) 13877c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 13887c478bd9Sstevel@tonic-gate 13897c478bd9Sstevel@tonic-gate if (*(subdir+1)) 13907c478bd9Sstevel@tonic-gate (void) strcat(dirname, subdir); 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate hl = hostlist; hlq = hostlistq; 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate host_cnt = 0; 13957c478bd9Sstevel@tonic-gate for (;;) { 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate if (getword(hostname_and_penalty, qbuff, &hl, &hlq, ',', 13987c478bd9Sstevel@tonic-gate sizeof (hostname_and_penalty)) == -1) 13997c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 14007c478bd9Sstevel@tonic-gate if (!*hostname_and_penalty) 14017c478bd9Sstevel@tonic-gate break; 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate host_cnt++; 14047c478bd9Sstevel@tonic-gate if (host_cnt > 1) 14057c478bd9Sstevel@tonic-gate maybe_url = FALSE; 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate hn = hostname_and_penalty; 14087c478bd9Sstevel@tonic-gate hnq = qbuff; 14097c478bd9Sstevel@tonic-gate if (getword(hostname, qbuff1, &hn, &hnq, '(', 14107c478bd9Sstevel@tonic-gate sizeof (hostname)) == -1) 14117c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 14127c478bd9Sstevel@tonic-gate if (hostname[0] == '\0') 14137c478bd9Sstevel@tonic-gate goto bad_entry; 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate if (strcmp(hostname, hostname_and_penalty) == 0) { 14167c478bd9Sstevel@tonic-gate penalty = 0; 14177c478bd9Sstevel@tonic-gate } else { 14187c478bd9Sstevel@tonic-gate maybe_url = FALSE; 14197c478bd9Sstevel@tonic-gate hn++; hnq++; 14207c478bd9Sstevel@tonic-gate if (getword(pbuff, pbuffq, &hn, &hnq, ')', 14217c478bd9Sstevel@tonic-gate sizeof (pbuff)) == -1) 14227c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 14237c478bd9Sstevel@tonic-gate if (!*pbuff) 14247c478bd9Sstevel@tonic-gate penalty = 0; 14257c478bd9Sstevel@tonic-gate else 14267c478bd9Sstevel@tonic-gate penalty = atoi(pbuff); 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate mfs = (struct mapfs *)malloc(sizeof (*mfs)); 14297c478bd9Sstevel@tonic-gate if (mfs == NULL) { 14307c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 14317c478bd9Sstevel@tonic-gate "parse_nfs: Memory allocation failed"); 14327c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 14337c478bd9Sstevel@tonic-gate } 14347c478bd9Sstevel@tonic-gate (void) memset(mfs, 0, sizeof (*mfs)); 14357c478bd9Sstevel@tonic-gate *mfsp = mfs; 14367c478bd9Sstevel@tonic-gate mfsp = &mfs->mfs_next; 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate if (maybe_url == TRUE) { 14397c478bd9Sstevel@tonic-gate char *host; 14407c478bd9Sstevel@tonic-gate char *path; 14417c478bd9Sstevel@tonic-gate char *sport; 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate host = dirname+2; 14447c478bd9Sstevel@tonic-gate path = strchr(host, '/'); 14457c478bd9Sstevel@tonic-gate if (path == NULL) { 14467c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 14477c478bd9Sstevel@tonic-gate "parse_nfs: illegal nfs url syntax: %s", 14487c478bd9Sstevel@tonic-gate host); 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate *path = '\0'; 14537c478bd9Sstevel@tonic-gate sport = strchr(host, ':'); 14547c478bd9Sstevel@tonic-gate 14557c478bd9Sstevel@tonic-gate if (sport != NULL && sport < path) { 14567c478bd9Sstevel@tonic-gate *sport = '\0'; 14577c478bd9Sstevel@tonic-gate mfs->mfs_port = atoi(sport+1); 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate if (mfs->mfs_port > USHRT_MAX) { 14607c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 14617c478bd9Sstevel@tonic-gate "parse_nfs: invalid " 14627c478bd9Sstevel@tonic-gate "port number (%d) in " 14637c478bd9Sstevel@tonic-gate "NFS URL", 14647c478bd9Sstevel@tonic-gate mfs->mfs_port); 14657c478bd9Sstevel@tonic-gate 14667c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate path++; 14727c478bd9Sstevel@tonic-gate if (*path == '\0') 14737c478bd9Sstevel@tonic-gate path = "."; 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate mfs->mfs_flags |= MFS_URL; 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate mfs->mfs_host = strdup(host); 14787c478bd9Sstevel@tonic-gate mfs->mfs_dir = strdup(path); 14797c478bd9Sstevel@tonic-gate } else { 14807c478bd9Sstevel@tonic-gate mfs->mfs_host = strdup(hostname); 14817c478bd9Sstevel@tonic-gate mfs->mfs_dir = strdup(dirname); 14827c478bd9Sstevel@tonic-gate } 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate mfs->mfs_penalty = penalty; 14857c478bd9Sstevel@tonic-gate if (mfs->mfs_host == NULL || mfs->mfs_dir == NULL) { 14867c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 14877c478bd9Sstevel@tonic-gate "parse_nfs: Memory allocation failed"); 14887c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 14897c478bd9Sstevel@tonic-gate } 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate /* 14927c478bd9Sstevel@tonic-gate * We check host_cnt to make sure we haven't parsed an entry 14937c478bd9Sstevel@tonic-gate * with no host information. 14947c478bd9Sstevel@tonic-gate */ 14957c478bd9Sstevel@tonic-gate if (host_cnt == 0) { 14967c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 14977c478bd9Sstevel@tonic-gate "parse_nfs: invalid host specified - bad entry " 14987c478bd9Sstevel@tonic-gate "in map %s \"%s\"", 14997c478bd9Sstevel@tonic-gate mapname, w); 15007c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate if (getword(w, wq, lp, lq, ' ', wsize) == -1) 15037c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate strcpy(fsw, w); 15077c478bd9Sstevel@tonic-gate strcpy(fswq, wq); 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate return (PARSE_OK); 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate bad_entry: 15127c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "parse_nfs: bad entry in map %s \"%s\"", mapname, w); 15137c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 15147c478bd9Sstevel@tonic-gate } 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate static int 15177c478bd9Sstevel@tonic-gate parse_special(me, w, wq, lp, lq, wsize) 15187c478bd9Sstevel@tonic-gate struct mapent *me; 15197c478bd9Sstevel@tonic-gate char *w, *wq, **lp, **lq; 15207c478bd9Sstevel@tonic-gate int wsize; 15217c478bd9Sstevel@tonic-gate { 15227c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN + 1], qbuf[MAXPATHLEN + 1]; 15237c478bd9Sstevel@tonic-gate char *wlp, *wlq; 15247c478bd9Sstevel@tonic-gate struct mapfs *mfs; 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate wlp = w; 15277c478bd9Sstevel@tonic-gate wlq = wq; 15287c478bd9Sstevel@tonic-gate if (getword(devname, qbuf, &wlp, &wlq, ' ', sizeof (devname)) == -1) 15297c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 15307c478bd9Sstevel@tonic-gate if (devname[0] == '\0') 15317c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate mfs = (struct mapfs *)malloc(sizeof (struct mapfs)); 15347c478bd9Sstevel@tonic-gate if (mfs == NULL) 15357c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 15367c478bd9Sstevel@tonic-gate (void) memset(mfs, 0, sizeof (*mfs)); 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate /* 15397c478bd9Sstevel@tonic-gate * A device name that begins with a slash could 15407c478bd9Sstevel@tonic-gate * be confused with a mountpoint path, hence use 15417c478bd9Sstevel@tonic-gate * a colon to escape a device string that begins 15427c478bd9Sstevel@tonic-gate * with a slash, e.g. 15437c478bd9Sstevel@tonic-gate * 15447c478bd9Sstevel@tonic-gate * foo -ro /bar foo:/bar 15457c478bd9Sstevel@tonic-gate * and 15467c478bd9Sstevel@tonic-gate * foo -ro /dev/sr0 15477c478bd9Sstevel@tonic-gate * 15487c478bd9Sstevel@tonic-gate * would confuse the parser. The second instance 15497c478bd9Sstevel@tonic-gate * must use a colon: 15507c478bd9Sstevel@tonic-gate * 15517c478bd9Sstevel@tonic-gate * foo -ro :/dev/sr0 15527c478bd9Sstevel@tonic-gate */ 15537c478bd9Sstevel@tonic-gate mfs->mfs_dir = strdup(&devname[devname[0] == ':']); 15547c478bd9Sstevel@tonic-gate if (mfs->mfs_dir == NULL) 15557c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 15567c478bd9Sstevel@tonic-gate me->map_fs = mfs; 15577c478bd9Sstevel@tonic-gate if (getword(w, wq, lp, lq, ' ', wsize) == -1) 15587c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 15597c478bd9Sstevel@tonic-gate return (0); 15607c478bd9Sstevel@tonic-gate } 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate /* 15637c478bd9Sstevel@tonic-gate * get_dir_from_path(char *dir, char **path, int dirsz) 15647c478bd9Sstevel@tonic-gate * gets the directory name dir from path for max string of length dirsz. 15657c478bd9Sstevel@tonic-gate * A modification of the getword routine. Assumes the delimiter is '/' 15667c478bd9Sstevel@tonic-gate * and that excess /'s are redundant. 15677c478bd9Sstevel@tonic-gate * Returns PARSE_OK or PARSE_ERROR 15687c478bd9Sstevel@tonic-gate */ 15697c478bd9Sstevel@tonic-gate static int 15707c478bd9Sstevel@tonic-gate get_dir_from_path(char *dir, char **path, int dirsz) 15717c478bd9Sstevel@tonic-gate { 15727c478bd9Sstevel@tonic-gate char *tmp = dir; 15737c478bd9Sstevel@tonic-gate int count = dirsz; 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate if (dirsz <= 0) { 15767c478bd9Sstevel@tonic-gate if (verbose) 15777c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 15787c478bd9Sstevel@tonic-gate "get_dir_from_path: invalid directory size %d", dirsz); 15797c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 15807c478bd9Sstevel@tonic-gate } 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate /* get rid of leading /'s in path */ 15837c478bd9Sstevel@tonic-gate while (**path == '/') 15847c478bd9Sstevel@tonic-gate (*path)++; 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate /* now at a word or at the end of path */ 15877c478bd9Sstevel@tonic-gate while ((**path) && ((**path) != '/')) { 15887c478bd9Sstevel@tonic-gate if (--count <= 0) { 15897c478bd9Sstevel@tonic-gate *tmp = '\0'; 15907c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 15917c478bd9Sstevel@tonic-gate "get_dir_from_path: max pathlength exceeded %d", dirsz); 15927c478bd9Sstevel@tonic-gate return (PARSE_ERROR); 15937c478bd9Sstevel@tonic-gate } 15947c478bd9Sstevel@tonic-gate *dir++ = *(*path)++; 15957c478bd9Sstevel@tonic-gate } 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate *dir = '\0'; 15987c478bd9Sstevel@tonic-gate 15997c478bd9Sstevel@tonic-gate /* get rid of trailing /'s in path */ 16007c478bd9Sstevel@tonic-gate while (**path == '/') 16017c478bd9Sstevel@tonic-gate (*path)++; 16027c478bd9Sstevel@tonic-gate 16037c478bd9Sstevel@tonic-gate return (PARSE_OK); 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate /* 16077c478bd9Sstevel@tonic-gate * alloc_hiernode(hiernode **newnode, char *dirname) 16087c478bd9Sstevel@tonic-gate * allocates a new hiernode corresponding to a new directory entry 16097c478bd9Sstevel@tonic-gate * in the hierarchical structure, and passes a pointer to it back 16107c478bd9Sstevel@tonic-gate * to the calling program. 16117c478bd9Sstevel@tonic-gate * Returns PARSE_OK or appropriate error value. 16127c478bd9Sstevel@tonic-gate */ 16137c478bd9Sstevel@tonic-gate static int 16147c478bd9Sstevel@tonic-gate alloc_hiernode(hiernode **newnode, char *dirname) 16157c478bd9Sstevel@tonic-gate { 16167c478bd9Sstevel@tonic-gate if ((*newnode = (hiernode *)malloc(sizeof (hiernode))) == NULL) { 16177c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "alloc_hiernode: Memory allocation failed"); 16187c478bd9Sstevel@tonic-gate return (ENOMEM); 16197c478bd9Sstevel@tonic-gate } 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate memset(((char *)*newnode), 0, sizeof (hiernode)); 16227c478bd9Sstevel@tonic-gate strcpy(((*newnode)->dirname), dirname); 16237c478bd9Sstevel@tonic-gate return (PARSE_OK); 16247c478bd9Sstevel@tonic-gate } 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate /* 16277c478bd9Sstevel@tonic-gate * free_hiernode(hiernode *node) 16287c478bd9Sstevel@tonic-gate * frees the allocated hiernode given the head of the structure 16297c478bd9Sstevel@tonic-gate * recursively calls itself until it frees entire structure. 16307c478bd9Sstevel@tonic-gate * Returns nothing. 16317c478bd9Sstevel@tonic-gate */ 16327c478bd9Sstevel@tonic-gate static void 16337c478bd9Sstevel@tonic-gate free_hiernode(hiernode *node) 16347c478bd9Sstevel@tonic-gate { 16357c478bd9Sstevel@tonic-gate hiernode *currnode = node; 16367c478bd9Sstevel@tonic-gate hiernode *prevnode = NULL; 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate while (currnode != NULL) { 16397c478bd9Sstevel@tonic-gate if (currnode->subdir != NULL) 16407c478bd9Sstevel@tonic-gate free_hiernode(currnode->subdir); 16417c478bd9Sstevel@tonic-gate prevnode = currnode; 16427c478bd9Sstevel@tonic-gate currnode = currnode->leveldir; 16437c478bd9Sstevel@tonic-gate free((void*)prevnode); 16447c478bd9Sstevel@tonic-gate } 16457c478bd9Sstevel@tonic-gate } 16467c478bd9Sstevel@tonic-gate 16477c478bd9Sstevel@tonic-gate /* 16487c478bd9Sstevel@tonic-gate * free_mapent(struct mapent *) 16497c478bd9Sstevel@tonic-gate * free the mapentry and its fields 16507c478bd9Sstevel@tonic-gate */ 16517c478bd9Sstevel@tonic-gate void 16527c478bd9Sstevel@tonic-gate free_mapent(me) 16537c478bd9Sstevel@tonic-gate struct mapent *me; 16547c478bd9Sstevel@tonic-gate { 16557c478bd9Sstevel@tonic-gate struct mapfs *mfs; 16567c478bd9Sstevel@tonic-gate struct mapent *m; 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate while (me) { 16597c478bd9Sstevel@tonic-gate while (me->map_fs) { 16607c478bd9Sstevel@tonic-gate mfs = me->map_fs; 16617c478bd9Sstevel@tonic-gate if (mfs->mfs_host) 16627c478bd9Sstevel@tonic-gate free(mfs->mfs_host); 16637c478bd9Sstevel@tonic-gate if (mfs->mfs_dir) 16647c478bd9Sstevel@tonic-gate free(mfs->mfs_dir); 16657c478bd9Sstevel@tonic-gate if (mfs->mfs_args) 16667c478bd9Sstevel@tonic-gate free(mfs->mfs_args); 16677c478bd9Sstevel@tonic-gate if (mfs->mfs_nconf) 16687c478bd9Sstevel@tonic-gate freenetconfigent(mfs->mfs_nconf); 16697c478bd9Sstevel@tonic-gate me->map_fs = mfs->mfs_next; 16707c478bd9Sstevel@tonic-gate free((char *)mfs); 16717c478bd9Sstevel@tonic-gate } 16727c478bd9Sstevel@tonic-gate 16737c478bd9Sstevel@tonic-gate if (me->map_root) 16747c478bd9Sstevel@tonic-gate free(me->map_root); 16757c478bd9Sstevel@tonic-gate if (me->map_mntpnt) 16767c478bd9Sstevel@tonic-gate free(me->map_mntpnt); 16777c478bd9Sstevel@tonic-gate if (me->map_mntopts) 16787c478bd9Sstevel@tonic-gate free(me->map_mntopts); 16797c478bd9Sstevel@tonic-gate if (me->map_fstype) 16807c478bd9Sstevel@tonic-gate free(me->map_fstype); 16817c478bd9Sstevel@tonic-gate if (me->map_mounter) 16827c478bd9Sstevel@tonic-gate free(me->map_mounter); 16837c478bd9Sstevel@tonic-gate if (me->map_fsw) 16847c478bd9Sstevel@tonic-gate free(me->map_fsw); 16857c478bd9Sstevel@tonic-gate if (me->map_fswq) 16867c478bd9Sstevel@tonic-gate free(me->map_fswq); 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate m = me; 16897c478bd9Sstevel@tonic-gate me = me->map_next; 16907c478bd9Sstevel@tonic-gate free((char *)m); 16917c478bd9Sstevel@tonic-gate } 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate /* 16957c478bd9Sstevel@tonic-gate * trace_mapents(struct mapent *mapents) 16967c478bd9Sstevel@tonic-gate * traces through the mapentry structure and prints it element by element 16977c478bd9Sstevel@tonic-gate * returns nothing 16987c478bd9Sstevel@tonic-gate */ 16997c478bd9Sstevel@tonic-gate static void 17007c478bd9Sstevel@tonic-gate trace_mapents(char *s, struct mapent *mapents) 17017c478bd9Sstevel@tonic-gate { 17027c478bd9Sstevel@tonic-gate struct mapfs *mfs; 17037c478bd9Sstevel@tonic-gate struct mapent *me; 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate trace_prt(1, "\n\t%s\n", s); 17067c478bd9Sstevel@tonic-gate for (me = mapents; me; me = me->map_next) { 17077c478bd9Sstevel@tonic-gate trace_prt(1, " (%s,%s)\t %s%s -%s\n", 17087c478bd9Sstevel@tonic-gate me->map_fstype ? me->map_fstype : "", 17097c478bd9Sstevel@tonic-gate me->map_mounter ? me->map_mounter : "", 17107c478bd9Sstevel@tonic-gate me->map_root ? me->map_root : "", 17117c478bd9Sstevel@tonic-gate me->map_mntpnt ? me->map_mntpnt : "", 17127c478bd9Sstevel@tonic-gate me->map_mntopts ? me->map_mntopts : ""); 17137c478bd9Sstevel@tonic-gate for (mfs = me->map_fs; mfs; mfs = mfs->mfs_next) 17147c478bd9Sstevel@tonic-gate trace_prt(0, "\t\t%s:%s\n", 17157c478bd9Sstevel@tonic-gate mfs->mfs_host ? mfs->mfs_host: "", 17167c478bd9Sstevel@tonic-gate mfs->mfs_dir ? mfs->mfs_dir : ""); 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate trace_prt(1, "\tme->map_fsw=%s\n", 17197c478bd9Sstevel@tonic-gate me->map_fsw ? me->map_fsw:"", 17207c478bd9Sstevel@tonic-gate me->map_fswq ? me->map_fsw:""); 17217c478bd9Sstevel@tonic-gate trace_prt(1, "\t mntlevel=%d\t%s\t%s err=%d\n", 17227c478bd9Sstevel@tonic-gate me->map_mntlevel, 17237c478bd9Sstevel@tonic-gate me->map_modified ? "modify=TRUE":"modify=FALSE", 17247c478bd9Sstevel@tonic-gate me->map_faked ? "faked=TRUE":"faked=FALSE", 17257c478bd9Sstevel@tonic-gate me->map_err); 17267c478bd9Sstevel@tonic-gate } 17277c478bd9Sstevel@tonic-gate } 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate /* 17307c478bd9Sstevel@tonic-gate * trace_hierarchy(hiernode *node) 17317c478bd9Sstevel@tonic-gate * traces the allocated hiernode given the head of the structure 17327c478bd9Sstevel@tonic-gate * recursively calls itself until it traces entire structure. 17337c478bd9Sstevel@tonic-gate * the first call made at the root is made with a zero level. 17347c478bd9Sstevel@tonic-gate * nodelevel is simply used to print tab and make the tracing clean. 17357c478bd9Sstevel@tonic-gate * Returns nothing. 17367c478bd9Sstevel@tonic-gate */ 17377c478bd9Sstevel@tonic-gate static void 17387c478bd9Sstevel@tonic-gate trace_hierarchy(hiernode *node, int nodelevel) 17397c478bd9Sstevel@tonic-gate { 17407c478bd9Sstevel@tonic-gate hiernode *currnode = node; 17417c478bd9Sstevel@tonic-gate int i; 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate while (currnode != NULL) { 17447c478bd9Sstevel@tonic-gate if (currnode->subdir != NULL) { 17457c478bd9Sstevel@tonic-gate for (i = 0; i < nodelevel; i++) 17467c478bd9Sstevel@tonic-gate trace_prt(0, "\t"); 17477c478bd9Sstevel@tonic-gate trace_prt(0, "\t(%s, ", 17487c478bd9Sstevel@tonic-gate currnode->dirname ? currnode->dirname :""); 17497c478bd9Sstevel@tonic-gate if (currnode->mapent) { 17507c478bd9Sstevel@tonic-gate trace_prt(0, "%d, %s)\n", 17517c478bd9Sstevel@tonic-gate currnode->mapent->map_mntlevel, 17527c478bd9Sstevel@tonic-gate currnode->mapent->map_mntopts ? 17537c478bd9Sstevel@tonic-gate currnode->mapent->map_mntopts:""); 17547c478bd9Sstevel@tonic-gate } 17557c478bd9Sstevel@tonic-gate else 17567c478bd9Sstevel@tonic-gate trace_prt(0, " ,)\n"); 17577c478bd9Sstevel@tonic-gate nodelevel++; 17587c478bd9Sstevel@tonic-gate trace_hierarchy(currnode->subdir, nodelevel); 17597c478bd9Sstevel@tonic-gate } else { 17607c478bd9Sstevel@tonic-gate for (i = 0; i < nodelevel; i++) 17617c478bd9Sstevel@tonic-gate trace_prt(0, "\t"); 17627c478bd9Sstevel@tonic-gate trace_prt(0, "\t(%s, ", 17637c478bd9Sstevel@tonic-gate currnode->dirname ? currnode->dirname :""); 17647c478bd9Sstevel@tonic-gate if (currnode->mapent) { 17657c478bd9Sstevel@tonic-gate trace_prt(0, "%d, %s)\n", 17667c478bd9Sstevel@tonic-gate currnode->mapent->map_mntlevel, 17677c478bd9Sstevel@tonic-gate currnode->mapent->map_mntopts ? 17687c478bd9Sstevel@tonic-gate currnode->mapent->map_mntopts:""); 17697c478bd9Sstevel@tonic-gate } 17707c478bd9Sstevel@tonic-gate else 17717c478bd9Sstevel@tonic-gate trace_prt(0, ", )\n"); 17727c478bd9Sstevel@tonic-gate } 17737c478bd9Sstevel@tonic-gate currnode = currnode->leveldir; 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate } 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate struct mapent * 17787c478bd9Sstevel@tonic-gate do_mapent_hosts(mapopts, host, isdirect) 17797c478bd9Sstevel@tonic-gate char *mapopts, *host; 17807c478bd9Sstevel@tonic-gate uint_t isdirect; 17817c478bd9Sstevel@tonic-gate { 17827c478bd9Sstevel@tonic-gate CLIENT *cl; 17837c478bd9Sstevel@tonic-gate struct mapent *me, *ms, *mp; 17847c478bd9Sstevel@tonic-gate struct mapfs *mfs; 17857c478bd9Sstevel@tonic-gate struct exportnode *ex = NULL; 17867c478bd9Sstevel@tonic-gate struct exportnode *exlist, *texlist, **texp, *exnext; 17877c478bd9Sstevel@tonic-gate struct timeval timeout; 17887c478bd9Sstevel@tonic-gate enum clnt_stat clnt_stat; 17897c478bd9Sstevel@tonic-gate char name[MAXPATHLEN]; 17907c478bd9Sstevel@tonic-gate char entryopts[MAXOPTSLEN]; 17917c478bd9Sstevel@tonic-gate char fstype[32], mounter[32]; 17927c478bd9Sstevel@tonic-gate int exlen, duplicate; 17937c478bd9Sstevel@tonic-gate struct mnttab mb; /* needed for hasmntopt() to get nfs version */ 17947c478bd9Sstevel@tonic-gate rpcvers_t nfsvers; /* version in map options, 0 if not there */ 17957c478bd9Sstevel@tonic-gate rpcvers_t vers, versmin; /* used to negotiate nfs vers in pingnfs() */ 17967c478bd9Sstevel@tonic-gate int retries, delay; 17977c478bd9Sstevel@tonic-gate int foundvers; 17987c478bd9Sstevel@tonic-gate 17997c478bd9Sstevel@tonic-gate if (trace > 1) 18007c478bd9Sstevel@tonic-gate trace_prt(1, " do_mapent_hosts: host %s\n", host); 18017c478bd9Sstevel@tonic-gate 18027c478bd9Sstevel@tonic-gate /* check for special case: host is me */ 18037c478bd9Sstevel@tonic-gate 18047c478bd9Sstevel@tonic-gate if (self_check(host)) { 18057c478bd9Sstevel@tonic-gate ms = (struct mapent *)malloc(sizeof (*ms)); 18067c478bd9Sstevel@tonic-gate if (ms == NULL) 18077c478bd9Sstevel@tonic-gate goto alloc_failed; 18087c478bd9Sstevel@tonic-gate (void) memset((char *)ms, 0, sizeof (*ms)); 18097c478bd9Sstevel@tonic-gate (void) strcpy(fstype, MNTTYPE_NFS); 18107c478bd9Sstevel@tonic-gate get_opts(mapopts, entryopts, fstype, NULL); 18117c478bd9Sstevel@tonic-gate ms->map_mntopts = strdup(entryopts); 18127c478bd9Sstevel@tonic-gate if (ms->map_mntopts == NULL) 18137c478bd9Sstevel@tonic-gate goto alloc_failed; 18147c478bd9Sstevel@tonic-gate ms->map_mounter = strdup(fstype); 18157c478bd9Sstevel@tonic-gate if (ms->map_mounter == NULL) 18167c478bd9Sstevel@tonic-gate goto alloc_failed; 18177c478bd9Sstevel@tonic-gate ms->map_fstype = strdup(MNTTYPE_NFS); 18187c478bd9Sstevel@tonic-gate if (ms->map_fstype == NULL) 18197c478bd9Sstevel@tonic-gate goto alloc_failed; 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate if (isdirect) 18227c478bd9Sstevel@tonic-gate name[0] = '\0'; 18237c478bd9Sstevel@tonic-gate else { 18247c478bd9Sstevel@tonic-gate (void) strcpy(name, "/"); 18257c478bd9Sstevel@tonic-gate (void) strcat(name, host); 18267c478bd9Sstevel@tonic-gate } 18277c478bd9Sstevel@tonic-gate ms->map_root = strdup(name); 18287c478bd9Sstevel@tonic-gate if (ms->map_root == NULL) 18297c478bd9Sstevel@tonic-gate goto alloc_failed; 18307c478bd9Sstevel@tonic-gate ms->map_mntpnt = strdup(""); 18317c478bd9Sstevel@tonic-gate if (ms->map_mntpnt == NULL) 18327c478bd9Sstevel@tonic-gate goto alloc_failed; 18337c478bd9Sstevel@tonic-gate mfs = (struct mapfs *)malloc(sizeof (*mfs)); 18347c478bd9Sstevel@tonic-gate if (mfs == NULL) 18357c478bd9Sstevel@tonic-gate goto alloc_failed; 18367c478bd9Sstevel@tonic-gate (void) memset((char *)mfs, 0, sizeof (*mfs)); 18377c478bd9Sstevel@tonic-gate ms->map_fs = mfs; 18387c478bd9Sstevel@tonic-gate mfs->mfs_host = strdup(host); 18397c478bd9Sstevel@tonic-gate if (mfs->mfs_host == NULL) 18407c478bd9Sstevel@tonic-gate goto alloc_failed; 18417c478bd9Sstevel@tonic-gate mfs->mfs_dir = strdup("/"); 18427c478bd9Sstevel@tonic-gate if (mfs->mfs_dir == NULL) 18437c478bd9Sstevel@tonic-gate goto alloc_failed; 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate /* initialize mntlevel and modify */ 18467c478bd9Sstevel@tonic-gate ms->map_mntlevel = -1; 18477c478bd9Sstevel@tonic-gate ms->map_modified = FALSE; 18487c478bd9Sstevel@tonic-gate ms->map_faked = FALSE; 18497c478bd9Sstevel@tonic-gate 18507c478bd9Sstevel@tonic-gate if (trace > 1) 18517c478bd9Sstevel@tonic-gate trace_prt(1, 18527c478bd9Sstevel@tonic-gate " do_mapent_hosts: self-host %s OK\n", host); 18537c478bd9Sstevel@tonic-gate 18547c478bd9Sstevel@tonic-gate return (ms); 18557c478bd9Sstevel@tonic-gate } 18567c478bd9Sstevel@tonic-gate 18577c478bd9Sstevel@tonic-gate /* 18587c478bd9Sstevel@tonic-gate * Call pingnfs. Note that we can't have replicated hosts in /net. 18597c478bd9Sstevel@tonic-gate * XXX - we would like to avoid duplicating the across the wire calls 18607c478bd9Sstevel@tonic-gate * made here in nfsmount(). The pingnfs cache should help avoid it. 18617c478bd9Sstevel@tonic-gate */ 18627c478bd9Sstevel@tonic-gate mb.mnt_mntopts = mapopts; 18637c478bd9Sstevel@tonic-gate foundvers = nopt(&mb, MNTOPT_VERS, (int *)&nfsvers); 18647c478bd9Sstevel@tonic-gate if (!foundvers) 18657c478bd9Sstevel@tonic-gate nfsvers = 0; 18667c478bd9Sstevel@tonic-gate if (set_versrange(nfsvers, &vers, &versmin) != 0) { 18677c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Incorrect NFS version specified for %s", host); 18687c478bd9Sstevel@tonic-gate return ((struct mapent *)NULL); 18697c478bd9Sstevel@tonic-gate } 18707c478bd9Sstevel@tonic-gate if (pingnfs(host, get_retry(mapopts) + 1, &vers, versmin, 0, FALSE, 18717c478bd9Sstevel@tonic-gate NULL, NULL) != RPC_SUCCESS) 18727c478bd9Sstevel@tonic-gate return ((struct mapent *)NULL); 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate retries = get_retry(mapopts); 18757c478bd9Sstevel@tonic-gate delay = INITDELAY; 18767c478bd9Sstevel@tonic-gate retry: 18777c478bd9Sstevel@tonic-gate /* get export list of host */ 18787c478bd9Sstevel@tonic-gate cl = clnt_create(host, MOUNTPROG, MOUNTVERS, "circuit_v"); 18797c478bd9Sstevel@tonic-gate if (cl == NULL) { 18807c478bd9Sstevel@tonic-gate cl = clnt_create(host, MOUNTPROG, MOUNTVERS, "datagram_v"); 18817c478bd9Sstevel@tonic-gate if (cl == NULL) { 18827c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 18837c478bd9Sstevel@tonic-gate "do_mapent_hosts: %s %s", host, clnt_spcreateerror("")); 18847c478bd9Sstevel@tonic-gate return ((struct mapent *)NULL); 18857c478bd9Sstevel@tonic-gate } 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate } 18887c478bd9Sstevel@tonic-gate #ifdef MALLOC_DEBUG 18897c478bd9Sstevel@tonic-gate add_alloc("CLNT_HANDLE", cl, 0, __FILE__, __LINE__); 18907c478bd9Sstevel@tonic-gate add_alloc("AUTH_HANDLE", cl->cl_auth, 0, 18917c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 18927c478bd9Sstevel@tonic-gate #endif 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate timeout.tv_usec = 0; 18957c478bd9Sstevel@tonic-gate timeout.tv_sec = 25; 18967c478bd9Sstevel@tonic-gate if (clnt_stat = clnt_call(cl, MOUNTPROC_EXPORT, xdr_void, 0, 18977c478bd9Sstevel@tonic-gate xdr_exports, (caddr_t)&ex, timeout)) { 18987c478bd9Sstevel@tonic-gate 18997c478bd9Sstevel@tonic-gate if (retries-- > 0) { 19007c478bd9Sstevel@tonic-gate clnt_destroy(cl); 19017c478bd9Sstevel@tonic-gate DELAY(delay); 19027c478bd9Sstevel@tonic-gate goto retry; 19037c478bd9Sstevel@tonic-gate } 19047c478bd9Sstevel@tonic-gate 19057c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 19067c478bd9Sstevel@tonic-gate "do_mapent_hosts: %s: export list: %s", 19077c478bd9Sstevel@tonic-gate host, clnt_sperrno(clnt_stat)); 19087c478bd9Sstevel@tonic-gate #ifdef MALLOC_DEBUG 19097c478bd9Sstevel@tonic-gate drop_alloc("CLNT_HANDLE", cl, __FILE__, __LINE__); 19107c478bd9Sstevel@tonic-gate drop_alloc("AUTH_HANDLE", cl->cl_auth, 19117c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 19127c478bd9Sstevel@tonic-gate #endif 19137c478bd9Sstevel@tonic-gate clnt_destroy(cl); 19147c478bd9Sstevel@tonic-gate return ((struct mapent *)NULL); 19157c478bd9Sstevel@tonic-gate } 19167c478bd9Sstevel@tonic-gate 19177c478bd9Sstevel@tonic-gate #ifdef MALLOC_DEBUG 19187c478bd9Sstevel@tonic-gate drop_alloc("CLNT_HANDLE", cl, __FILE__, __LINE__); 19197c478bd9Sstevel@tonic-gate drop_alloc("AUTH_HANDLE", cl->cl_auth, 19207c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 19217c478bd9Sstevel@tonic-gate #endif 19227c478bd9Sstevel@tonic-gate clnt_destroy(cl); 19237c478bd9Sstevel@tonic-gate 19247c478bd9Sstevel@tonic-gate if (ex == NULL) { 19257c478bd9Sstevel@tonic-gate if (trace > 1) 19267c478bd9Sstevel@tonic-gate trace_prt(1, 19277c478bd9Sstevel@tonic-gate gettext(" getmapent_hosts: null export list\n")); 19287c478bd9Sstevel@tonic-gate return ((struct mapent *)NULL); 19297c478bd9Sstevel@tonic-gate } 19307c478bd9Sstevel@tonic-gate 19317c478bd9Sstevel@tonic-gate /* now sort by length of names - to get mount order right */ 19327c478bd9Sstevel@tonic-gate exlist = ex; 19337c478bd9Sstevel@tonic-gate texlist = NULL; 19347c478bd9Sstevel@tonic-gate #ifdef lint 19357c478bd9Sstevel@tonic-gate exnext = NULL; 19367c478bd9Sstevel@tonic-gate #endif 19377c478bd9Sstevel@tonic-gate for (; ex; ex = exnext) { 19387c478bd9Sstevel@tonic-gate exnext = ex->ex_next; 19397c478bd9Sstevel@tonic-gate exlen = strlen(ex->ex_dir); 19407c478bd9Sstevel@tonic-gate duplicate = 0; 19417c478bd9Sstevel@tonic-gate for (texp = &texlist; *texp; texp = &((*texp)->ex_next)) { 19427c478bd9Sstevel@tonic-gate if (exlen < (int)strlen((*texp)->ex_dir)) 19437c478bd9Sstevel@tonic-gate break; 19447c478bd9Sstevel@tonic-gate duplicate = (strcmp(ex->ex_dir, (*texp)->ex_dir) == 0); 19457c478bd9Sstevel@tonic-gate if (duplicate) { 19467c478bd9Sstevel@tonic-gate /* disregard duplicate entry */ 19477c478bd9Sstevel@tonic-gate freeex_ent(ex); 19487c478bd9Sstevel@tonic-gate break; 19497c478bd9Sstevel@tonic-gate } 19507c478bd9Sstevel@tonic-gate } 19517c478bd9Sstevel@tonic-gate if (!duplicate) { 19527c478bd9Sstevel@tonic-gate ex->ex_next = *texp; 19537c478bd9Sstevel@tonic-gate *texp = ex; 19547c478bd9Sstevel@tonic-gate } 19557c478bd9Sstevel@tonic-gate } 19567c478bd9Sstevel@tonic-gate exlist = texlist; 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate (void) strcpy(fstype, MNTTYPE_NFS); 19597c478bd9Sstevel@tonic-gate get_opts(mapopts, entryopts, fstype, NULL); 19607c478bd9Sstevel@tonic-gate (void) strcpy(mounter, fstype); 19617c478bd9Sstevel@tonic-gate 19627c478bd9Sstevel@tonic-gate /* Now create a mapent from the export list */ 19637c478bd9Sstevel@tonic-gate ms = NULL; 19647c478bd9Sstevel@tonic-gate me = NULL; 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate for (ex = exlist; ex; ex = ex->ex_next) { 19677c478bd9Sstevel@tonic-gate mp = me; 19687c478bd9Sstevel@tonic-gate me = (struct mapent *)malloc(sizeof (*me)); 19697c478bd9Sstevel@tonic-gate if (me == NULL) 19707c478bd9Sstevel@tonic-gate goto alloc_failed; 19717c478bd9Sstevel@tonic-gate (void) memset((char *)me, 0, sizeof (*me)); 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate if (ms == NULL) 19747c478bd9Sstevel@tonic-gate ms = me; 19757c478bd9Sstevel@tonic-gate else 19767c478bd9Sstevel@tonic-gate mp->map_next = me; 19777c478bd9Sstevel@tonic-gate 19787c478bd9Sstevel@tonic-gate if (isdirect) 19797c478bd9Sstevel@tonic-gate name[0] = '\0'; 19807c478bd9Sstevel@tonic-gate else { 19817c478bd9Sstevel@tonic-gate (void) strcpy(name, "/"); 19827c478bd9Sstevel@tonic-gate (void) strcat(name, host); 19837c478bd9Sstevel@tonic-gate } 19847c478bd9Sstevel@tonic-gate me->map_root = strdup(name); 19857c478bd9Sstevel@tonic-gate if (me->map_root == NULL) 19867c478bd9Sstevel@tonic-gate goto alloc_failed; 19877c478bd9Sstevel@tonic-gate 19887c478bd9Sstevel@tonic-gate *name = '\0'; 19897c478bd9Sstevel@tonic-gate if (strcmp(ex->ex_dir, "/") != 0) { 19907c478bd9Sstevel@tonic-gate if (*(ex->ex_dir) != '/') 19917c478bd9Sstevel@tonic-gate (void) strcpy(name, "/"); 19927c478bd9Sstevel@tonic-gate (void) strcat(name, ex->ex_dir); 19937c478bd9Sstevel@tonic-gate } 19947c478bd9Sstevel@tonic-gate me->map_mntpnt = strdup(name); 19957c478bd9Sstevel@tonic-gate if (me->map_mntpnt == NULL) 19967c478bd9Sstevel@tonic-gate goto alloc_failed; 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate me->map_fstype = strdup(fstype); 19997c478bd9Sstevel@tonic-gate if (me->map_fstype == NULL) 20007c478bd9Sstevel@tonic-gate goto alloc_failed; 20017c478bd9Sstevel@tonic-gate me->map_mounter = strdup(mounter); 20027c478bd9Sstevel@tonic-gate if (me->map_mounter == NULL) 20037c478bd9Sstevel@tonic-gate goto alloc_failed; 20047c478bd9Sstevel@tonic-gate me->map_mntopts = strdup(entryopts); 20057c478bd9Sstevel@tonic-gate if (me->map_mntopts == NULL) 20067c478bd9Sstevel@tonic-gate goto alloc_failed; 20077c478bd9Sstevel@tonic-gate 20087c478bd9Sstevel@tonic-gate mfs = (struct mapfs *)malloc(sizeof (*mfs)); 20097c478bd9Sstevel@tonic-gate if (mfs == NULL) 20107c478bd9Sstevel@tonic-gate goto alloc_failed; 20117c478bd9Sstevel@tonic-gate (void) memset((char *)mfs, 0, sizeof (*mfs)); 20127c478bd9Sstevel@tonic-gate me->map_fs = mfs; 20137c478bd9Sstevel@tonic-gate mfs->mfs_host = strdup(host); 20147c478bd9Sstevel@tonic-gate if (mfs->mfs_host == NULL) 20157c478bd9Sstevel@tonic-gate goto alloc_failed; 20167c478bd9Sstevel@tonic-gate mfs->mfs_dir = strdup(ex->ex_dir); 20177c478bd9Sstevel@tonic-gate if (mfs->mfs_dir == NULL) 20187c478bd9Sstevel@tonic-gate goto alloc_failed; 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate /* initialize mntlevel and modify values */ 20217c478bd9Sstevel@tonic-gate me->map_mntlevel = -1; 20227c478bd9Sstevel@tonic-gate me->map_modified = FALSE; 20237c478bd9Sstevel@tonic-gate me->map_faked = FALSE; 20247c478bd9Sstevel@tonic-gate } 20257c478bd9Sstevel@tonic-gate freeex(exlist); 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate if (trace > 1) 20287c478bd9Sstevel@tonic-gate trace_prt(1, " do_mapent_hosts: host %s OK\n", host); 20297c478bd9Sstevel@tonic-gate 20307c478bd9Sstevel@tonic-gate return (ms); 20317c478bd9Sstevel@tonic-gate 20327c478bd9Sstevel@tonic-gate alloc_failed: 20337c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "do_mapent_hosts: Memory allocation failed"); 20347c478bd9Sstevel@tonic-gate free_mapent(ms); 20357c478bd9Sstevel@tonic-gate freeex(exlist); 20367c478bd9Sstevel@tonic-gate return ((struct mapent *)NULL); 20377c478bd9Sstevel@tonic-gate } 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate static void 20417c478bd9Sstevel@tonic-gate freeex_ent(ex) 20427c478bd9Sstevel@tonic-gate struct exportnode *ex; 20437c478bd9Sstevel@tonic-gate { 20447c478bd9Sstevel@tonic-gate struct groupnode *groups, *tmpgroups; 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate free(ex->ex_dir); 20477c478bd9Sstevel@tonic-gate groups = ex->ex_groups; 20487c478bd9Sstevel@tonic-gate while (groups) { 20497c478bd9Sstevel@tonic-gate free(groups->gr_name); 20507c478bd9Sstevel@tonic-gate tmpgroups = groups->gr_next; 20517c478bd9Sstevel@tonic-gate free((char *)groups); 20527c478bd9Sstevel@tonic-gate groups = tmpgroups; 20537c478bd9Sstevel@tonic-gate } 20547c478bd9Sstevel@tonic-gate free((char *)ex); 20557c478bd9Sstevel@tonic-gate } 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate static void 20587c478bd9Sstevel@tonic-gate freeex(ex) 20597c478bd9Sstevel@tonic-gate struct exportnode *ex; 20607c478bd9Sstevel@tonic-gate { 20617c478bd9Sstevel@tonic-gate struct exportnode *tmpex; 20627c478bd9Sstevel@tonic-gate 20637c478bd9Sstevel@tonic-gate while (ex) { 20647c478bd9Sstevel@tonic-gate tmpex = ex->ex_next; 20657c478bd9Sstevel@tonic-gate freeex_ent(ex); 20667c478bd9Sstevel@tonic-gate ex = tmpex; 20677c478bd9Sstevel@tonic-gate } 20687c478bd9Sstevel@tonic-gate } 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate static const char uatfs_err[] = "submount under fstype=autofs not supported"; 20717c478bd9Sstevel@tonic-gate /* 20727c478bd9Sstevel@tonic-gate * dump_mapent_err(struct mapent *me, char *key, char *mapname) 20737c478bd9Sstevel@tonic-gate * syslog appropriate error in mapentries. 20747c478bd9Sstevel@tonic-gate */ 20757c478bd9Sstevel@tonic-gate static void dump_mapent_err(struct mapent *me, char *key, char *mapname) 20767c478bd9Sstevel@tonic-gate { 20777c478bd9Sstevel@tonic-gate switch (me->map_err) { 20787c478bd9Sstevel@tonic-gate case MAPENT_NOERR: 20797c478bd9Sstevel@tonic-gate if (verbose) 20807c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 20817c478bd9Sstevel@tonic-gate "map=%s key=%s mntpnt=%s: no error"); 20827c478bd9Sstevel@tonic-gate break; 20837c478bd9Sstevel@tonic-gate case MAPENT_UATFS: 20847c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 20857c478bd9Sstevel@tonic-gate "mountpoint %s in map %s key %s not mounted: %s", 20867c478bd9Sstevel@tonic-gate me->map_mntpnt, mapname, key, uatfs_err); 20877c478bd9Sstevel@tonic-gate break; 20887c478bd9Sstevel@tonic-gate default: 20897c478bd9Sstevel@tonic-gate if (verbose) 20907c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 20917c478bd9Sstevel@tonic-gate "map=%s key=%s mntpnt=%s: unknown mapentry error"); 20927c478bd9Sstevel@tonic-gate } 20937c478bd9Sstevel@tonic-gate } 2094