#pragma ident "@(#)autod_autofs.c 1.27 05/06/08 SMI"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/param.h>
#include <mntopts.h>
#include <syslog.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#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);
}
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;
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 {
if ((alp->mounta.key = strdup(alp->mounta.path)) == NULL)
goto free_mem;
}
} else {
alp->mounta.key = NULL;
}
if ((alp->mounta.dir = strdup(rel_mntpnt)) == NULL)
goto free_mem;
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:
syslog(LOG_ERR, "mount_autofs: memory allocation failure");
free_action_list_fields(alp);
return (ENOMEM);
}
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) {
if (options[0] != '\0') {
CHECK_STRCAT(options, ",", AUTOFS_MAXOPTSLEN);
}
CHECK_STRCAT(options, MNTOPT_RDDIR, AUTOFS_MAXOPTSLEN);
} else if (strcmp(opt, "nobrowse") == 0) {
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);
}
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);
}