/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * autod_autofs.c * * Copyright (c) 1988-1996 Sun Microsystems Inc * All Rights Reserved. */ /* * Portions Copyright 2007-2009 Apple Inc. */ #pragma ident "@(#)autod_autofs.c 1.27 05/06/08 SMI" #include #include #include #include #include #include #include #include #include #include "automount.h" static int process_opts(char *options, uint32_t *directp); static const struct mntopt mopts_autofs[] = { MOPT_STDOPTS, { MNTOPT_RESTRICT, 0, AUTOFS_MNT_RESTRICT, 1 }, { MNTOPT_RDDIR, 1, AUTOFS_MNT_NORDDIR, 1 }, { MNTOPT_HIDEFROMFINDER, 0, AUTOFS_MNT_HIDEFROMFINDER, 1 }, { NULL, 0, 0, 0 } }; int mount_autofs( struct mapent *me, char *mntpnt, action_list *alp, char *rootp, char *subdir, char *key ) { char rel_mntpnt[MAXPATHLEN]; mntoptparse_t mp; if (trace > 1) trace_prt(1, " mount_autofs %s on %s\n", me->map_fs->mfs_dir, mntpnt); if (strcmp(mntpnt, "/-") == 0) { syslog(LOG_ERR, "invalid mountpoint: /-"); return (ENOENT); } /* * get relative mountpoint */ if (snprintf(rel_mntpnt, sizeof (rel_mntpnt), ".%s", mntpnt+strlen(rootp)) >= (int)sizeof (rel_mntpnt)) { syslog(LOG_ERR, "mountpoint too long: %s", mntpnt); return (ENOENT); } if (trace > 2) trace_prt(1, "rel_mntpnt = %s\n", rel_mntpnt); if ((alp->mounta.opts = malloc(AUTOFS_MAXOPTSLEN)) == NULL) goto free_mem; if (strlcpy(alp->mounta.opts, me->map_mntopts, AUTOFS_MAXOPTSLEN) >= AUTOFS_MAXOPTSLEN) { syslog(LOG_ERR, "options \"%s\" for %s are too long", me->map_mntopts, mntpnt); free(alp->mounta.opts); return (ENOENT); } if (process_opts(alp->mounta.opts, &alp->mounta.isdirect) != 0) goto free_mem; /* * get absolute mountpoint */ if ((alp->mounta.path = strdup(mntpnt)) == NULL) goto free_mem; if ((alp->mounta.map = strdup(me->map_fs->mfs_dir)) == NULL) goto free_mem; if ((alp->mounta.subdir = strdup(subdir)) == NULL) goto free_mem; if (alp->mounta.isdirect) { if (me->map_modified == TRUE || me->map_faked == TRUE) { if ((alp->mounta.key = strdup(key)) == NULL) goto free_mem; } else { /* wierd case of a direct map pointer in another map */ if ((alp->mounta.key = strdup(alp->mounta.path)) == NULL) goto free_mem; } } else { alp->mounta.key = NULL; } /* * Fill out action list. */ if ((alp->mounta.dir = strdup(rel_mntpnt)) == NULL) goto free_mem; /* * Parse the mount options and fill in "flags" and "mntflags". */ alp->mounta.flags = alp->mounta.mntflags = 0; getmnt_silent = 1; mp = getmntopts(alp->mounta.opts, mopts_autofs, &alp->mounta.flags, &alp->mounta.mntflags); if (mp == NULL) goto free_mem; freemntopts(mp); return (0); free_mem: /* * We got an error, free the memory we allocated. */ syslog(LOG_ERR, "mount_autofs: memory allocation failure"); free_action_list_fields(alp); return (ENOMEM); } /* * Set *directp to 1 if "direct" is found, and 0 otherwise * (mounts are indirect by default). If both "direct" and "indirect" are * found, the last one wins. * * Also, map "browse"/"nobrowse" to "rddir"/"norddir". */ static int process_opts(char *options, uint32_t *directp) { char *opt, *opts, *lasts; char buf[AUTOFS_MAXOPTSLEN]; CHECK_STRCPY(buf, options, sizeof buf); opts = buf; options[0] = '\0'; *directp = 0; while ((opt = strtok_r(opts, ",", &lasts)) != NULL) { opts = NULL; while (isspace(*opt)) { opt++; } if (strcmp(opt, "direct") == 0) { *directp = 1; } else if (strcmp(opt, "indirect") == 0) { *directp = 0; } else if (strcmp(opt, "browse") == 0) { /* * We already have a "browse" option, which * governs whether the file system will show * up on the desktop and in the sidebar; map * Solaris's "browse" option, which governs * whether readdir is supported on an autofs * file system, to our "rddir" option. */ if (options[0] != '\0') { CHECK_STRCAT(options, ",", AUTOFS_MAXOPTSLEN); } CHECK_STRCAT(options, MNTOPT_RDDIR, AUTOFS_MAXOPTSLEN); } else if (strcmp(opt, "nobrowse") == 0) { /* * As with "browse" and "rddir", so with * "nobrowse" and "norddir". */ if (options[0] != '\0') { CHECK_STRCAT(options, ",", AUTOFS_MAXOPTSLEN); } CHECK_STRCAT(options, "no" MNTOPT_RDDIR, AUTOFS_MAXOPTSLEN); } else if (strcmp(opt, "ignore") != 0) { if (options[0] != '\0') { CHECK_STRCAT(options, ",", AUTOFS_MAXOPTSLEN); } CHECK_STRCAT(options, opt, AUTOFS_MAXOPTSLEN); } }; return (0); } /* * free items pointed to by members of an action list structure */ void free_action_list_fields(action_list *alp) { if (alp == NULL) return; if (alp->mounta.dir) free(alp->mounta.dir); if (alp->mounta.opts) free(alp->mounta.opts); if (alp->mounta.path) free(alp->mounta.path); if (alp->mounta.map) free(alp->mounta.map); if (alp->mounta.subdir) free(alp->mounta.subdir); if (alp->mounta.key) free(alp->mounta.key); }