|
Packit |
8480eb |
/* ----------------------------------------------------------------------- *
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Copyright 2013 Ian Kent <raven@themaw.net>
|
|
Packit |
8480eb |
* Copyright 2013 Red Hat, Inc.
|
|
Packit |
8480eb |
* All rights reserved.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
8480eb |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
8480eb |
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
|
|
Packit |
8480eb |
* USA; either version 2 of the License, or (at your option) any later
|
|
Packit |
8480eb |
* version; incorporated herein by reference.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* ----------------------------------------------------------------------- */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#include <stdio.h>
|
|
Packit |
8480eb |
#include <malloc.h>
|
|
Packit |
8480eb |
#include <netdb.h>
|
|
Packit |
8480eb |
#include <stdlib.h>
|
|
Packit |
8480eb |
#include <string.h>
|
|
Packit |
8480eb |
#include <ctype.h>
|
|
Packit |
8480eb |
#include <limits.h>
|
|
Packit |
8480eb |
#include <sys/param.h>
|
|
Packit |
8480eb |
#include <sys/socket.h>
|
|
Packit |
8480eb |
#include <sys/types.h>
|
|
Packit |
8480eb |
#include <sys/stat.h>
|
|
Packit |
8480eb |
#include <sys/vfs.h>
|
|
Packit |
8480eb |
#include <sys/utsname.h>
|
|
Packit |
8480eb |
#include <netinet/in.h>
|
|
Packit |
8480eb |
#include <sys/mount.h>
|
|
Packit |
8480eb |
#include <linux/fs.h>
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MODULE_PARSE
|
|
Packit |
8480eb |
#include "automount.h"
|
|
Packit |
8480eb |
#include "nsswitch.h"
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MODPREFIX "parse(amd): "
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int parse_version = AUTOFS_PARSE_VERSION; /* Required by protocol */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct mount_mod *mount_nfs = NULL;
|
|
Packit |
8480eb |
static int init_ctr = 0;
|
|
Packit |
8480eb |
static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void instance_mutex_lock(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status = pthread_mutex_lock(&instance_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void instance_mutex_unlock(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status = pthread_mutex_unlock(&instance_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
extern const char *global_options;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct parse_context {
|
|
Packit |
8480eb |
char *optstr; /* Mount options */
|
|
Packit |
8480eb |
char *macros; /* Map wide macro defines */
|
|
Packit |
8480eb |
struct substvar *subst; /* $-substitutions */
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct multi_mnt {
|
|
Packit |
8480eb |
char *path;
|
|
Packit |
8480eb |
char *options;
|
|
Packit |
8480eb |
char *location;
|
|
Packit |
8480eb |
struct multi_mnt *next;
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Default context */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct parse_context default_context = {
|
|
Packit |
8480eb |
NULL, /* No mount options */
|
|
Packit |
8480eb |
NULL, /* No map wide macros */
|
|
Packit |
8480eb |
NULL /* The substvar local vars table */
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Free all storage associated with this context */
|
|
Packit |
8480eb |
static void kill_context(struct parse_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
macro_lock();
|
|
Packit |
8480eb |
macro_free_table(ctxt->subst);
|
|
Packit |
8480eb |
macro_unlock();
|
|
Packit |
8480eb |
if (ctxt->optstr)
|
|
Packit |
8480eb |
free(ctxt->optstr);
|
|
Packit |
8480eb |
if (ctxt->macros)
|
|
Packit |
8480eb |
free(ctxt->macros);
|
|
Packit |
8480eb |
free(ctxt);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int parse_init(int argc, const char *const *argv, void **context)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct parse_context *ctxt;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sel_hash_init();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Set up context and escape chain */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!(ctxt = (struct parse_context *) malloc(sizeof(struct parse_context)))) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
*context = NULL;
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
*context = (void *) ctxt;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*ctxt = default_context;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* We only need this once. NFS mounts are so common that we cache
|
|
Packit |
8480eb |
this module. */
|
|
Packit |
8480eb |
instance_mutex_lock();
|
|
Packit |
8480eb |
if (mount_nfs)
|
|
Packit |
8480eb |
init_ctr++;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
if ((mount_nfs = open_mount("nfs", MODPREFIX))) {
|
|
Packit |
8480eb |
init_ctr++;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
kill_context(ctxt);
|
|
Packit |
8480eb |
*context = NULL;
|
|
Packit |
8480eb |
instance_mutex_unlock();
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
instance_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int parse_reinit(int argc, const char *const *argv, void **context)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct substvar *add_lookup_vars(struct autofs_point *ap,
|
|
Packit |
8480eb |
const char *key, int key_len,
|
|
Packit |
8480eb |
struct map_source *source,
|
|
Packit |
8480eb |
struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct substvar *list = sv;
|
|
Packit |
8480eb |
struct thread_stdenv_vars *tsv;
|
|
Packit |
8480eb |
char lkp_key[PATH_MAX + 1];
|
|
Packit |
8480eb |
char path[PATH_MAX + 1];
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
int len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = strlen(ap->path) + 1 + key_len + 1;
|
|
Packit |
8480eb |
if (len > PATH_MAX) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"error: lookup key is greater than PATH_MAX");
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->pref) {
|
|
Packit |
8480eb |
if (snprintf(lkp_key, sizeof(lkp_key), "%s%s",
|
|
Packit |
8480eb |
ap->pref, key) >= sizeof(lkp_key)) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "key too long");
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (snprintf(lkp_key, sizeof(lkp_key), "%s",
|
|
Packit |
8480eb |
key) >= sizeof(lkp_key)) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "key too long");
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*key == '/')
|
|
Packit |
8480eb |
strcpy(path, key);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
strcpy(path, ap->path);
|
|
Packit |
8480eb |
strcat(path, "/");
|
|
Packit |
8480eb |
strcat(path, key);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
list = macro_addvar(list, "path", 4, path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
me = cache_lookup_distinct(source->mc, lkp_key);
|
|
Packit |
8480eb |
if (me)
|
|
Packit |
8480eb |
list = macro_addvar(list, "key", 3, me->key);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (!me) {
|
|
Packit |
8480eb |
char match[PATH_MAX + 1];
|
|
Packit |
8480eb |
char *prefix;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(match, lkp_key);
|
|
Packit |
8480eb |
while ((prefix = strrchr(match, '/'))) {
|
|
Packit |
8480eb |
*prefix = '\0';
|
|
Packit |
8480eb |
me = cache_partial_match_wild(source->mc, match);
|
|
Packit |
8480eb |
if (me) {
|
|
Packit |
8480eb |
list = macro_addvar(list, "key", 3, lkp_key);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!me) {
|
|
Packit |
8480eb |
me = cache_lookup_distinct(source->mc, "*");
|
|
Packit |
8480eb |
if (me)
|
|
Packit |
8480eb |
list = macro_addvar(list, "key", 3, lkp_key);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (source->name)
|
|
Packit |
8480eb |
list = macro_addvar(list, "map", 3, source->name);
|
|
Packit |
8480eb |
else if (source->argv[0][0])
|
|
Packit |
8480eb |
list = macro_addvar(list, "map", 3, source->argv[0]);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tsv = pthread_getspecific(key_thread_stdenv_vars);
|
|
Packit |
8480eb |
if (tsv) {
|
|
Packit |
8480eb |
char numbuf[16];
|
|
Packit |
8480eb |
long num;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
num = (long) tsv->uid;
|
|
Packit |
8480eb |
ret = sprintf(numbuf, "%ld", num);
|
|
Packit |
8480eb |
if (ret > 0)
|
|
Packit |
8480eb |
list = macro_addvar(list, "uid", 3, numbuf);
|
|
Packit |
8480eb |
num = (long) tsv->gid;
|
|
Packit |
8480eb |
ret = sprintf(numbuf, "%ld", num);
|
|
Packit |
8480eb |
if (ret > 0)
|
|
Packit |
8480eb |
list = macro_addvar(list, "gid", 3, numbuf);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
list = macro_addvar(list, "fs", 2, "${autodir}/${rhost}${rfs}");
|
|
Packit |
8480eb |
list = macro_addvar(list, "rfs", 3, path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return list;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Service |
145c60 |
static int match_my_name(unsigned int logopt, const char *name, struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct addrinfo hints, *cni, *ni, *haddr;
|
|
Packit |
8480eb |
char host[NI_MAXHOST + 1], numeric[NI_MAXHOST + 1];
|
|
Packit |
8480eb |
const struct substvar *v;
|
|
Packit |
8480eb |
int rv = 0, ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
v = macro_findvar(sv, "host", 4);
|
|
Packit |
8480eb |
if (v) {
|
|
Packit Service |
145c60 |
if (!strcmp(v->val, name))
|
|
Packit Service |
145c60 |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!v || !v->val) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX "error: ${host} not set");
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Check if comparison value is an alias */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
memset(&hints, 0, sizeof(hints));
|
|
Packit |
8480eb |
hints.ai_flags = AI_CANONNAME;
|
|
Packit |
8480eb |
hints.ai_family = AF_UNSPEC;
|
|
Packit |
8480eb |
hints.ai_socktype = SOCK_DGRAM;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Get host canonical name */
|
|
Packit |
8480eb |
ret = getaddrinfo(v->val, NULL, &hints, &cni);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"hostname lookup failed: %s\n", gai_strerror(ret));
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Resolve comparison name to its names and compare */
|
|
Packit Service |
145c60 |
ret = getaddrinfo(name, NULL, &hints, &ni);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"hostname lookup failed: %s\n", gai_strerror(ret));
|
|
Packit |
8480eb |
freeaddrinfo(cni);
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
haddr = ni;
|
|
Packit |
8480eb |
while (haddr) {
|
|
Packit |
8480eb |
/* Translate the host address into a numeric string form */
|
|
Packit |
8480eb |
ret = getnameinfo(haddr->ai_addr, haddr->ai_addrlen,
|
|
Packit |
8480eb |
numeric, sizeof(numeric), NULL, 0,
|
|
Packit |
8480eb |
NI_NUMERICHOST);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"host address info lookup failed: %s\n",
|
|
Packit |
8480eb |
gai_strerror(ret));
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Try to resolve back again to get the canonical name */
|
|
Packit |
8480eb |
ret = getnameinfo(haddr->ai_addr, haddr->ai_addrlen,
|
|
Packit |
8480eb |
host, NI_MAXHOST, NULL, 0, 0);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"host address info lookup failed: %s\n",
|
|
Packit |
8480eb |
gai_strerror(ret));
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(host, cni->ai_canonname)) {
|
|
Packit |
8480eb |
rv = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
next:
|
|
Packit |
8480eb |
haddr = haddr->ai_next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
freeaddrinfo(ni);
|
|
Packit |
8480eb |
freeaddrinfo(cni);
|
|
Packit |
8480eb |
out:
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Service |
145c60 |
static int eval_selector(unsigned int logopt,
|
|
Packit |
8480eb |
struct amd_entry *this, struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct selector *s = this->selector;
|
|
Packit |
8480eb |
const struct substvar *v;
|
|
Packit |
8480eb |
unsigned int s_type;
|
|
Packit |
8480eb |
unsigned int v_type;
|
|
Packit Service |
145c60 |
struct stat st;
|
|
Packit Service |
145c60 |
char *host;
|
|
Packit |
8480eb |
int res, val, ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
s_type = s->sel->flags & SEL_FLAGS_TYPE_MASK;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (s_type) {
|
|
Packit |
8480eb |
case SEL_FLAG_MACRO:
|
|
Packit |
8480eb |
v = macro_findvar(sv, s->sel->name, strlen(s->sel->name));
|
|
Packit |
8480eb |
if (!v) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to get selector %s", s->sel->name);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
v_type = s->sel->flags & SEL_FLAGS_VALUE_MASK;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (v_type) {
|
|
Packit |
8480eb |
case SEL_FLAG_STR:
|
|
Packit Service |
145c60 |
res = strcmp(v->val, s->comp.value);
|
|
Packit Service |
145c60 |
if (s->compare & SEL_COMP_EQUAL && !res) {
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"matched selector %s(%s) == %s",
|
|
Packit Service |
145c60 |
v->def, v->val, s->comp.value);
|
|
Packit Service |
145c60 |
ret = 1;
|
|
Packit Service |
145c60 |
break;
|
|
Packit Service |
145c60 |
} else if (s->compare & SEL_COMP_NOTEQUAL && res) {
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"matched selector %s(%s) != %s",
|
|
Packit Service |
145c60 |
v->def, v->val, s->comp.value);
|
|
Packit Service |
145c60 |
ret = 1;
|
|
Packit Service |
145c60 |
break;
|
|
Packit Service |
145c60 |
}
|
|
Packit Service |
145c60 |
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"did not match selector %s(%s) %s %s",
|
|
Packit Service |
145c60 |
v->def, v->val,
|
|
Packit Service |
145c60 |
(s->compare & SEL_COMP_EQUAL ? "==" : "!="),
|
|
Packit Service |
145c60 |
s->comp.value);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case SEL_FLAG_NUM:
|
|
Packit |
8480eb |
if (!*s->comp.value) {
|
|
Packit |
8480eb |
res = 1;
|
|
Packit |
8480eb |
val = 0;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
res = atoi(v->val);
|
|
Packit |
8480eb |
val = atoi(s->comp.value);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (s->compare & SEL_COMP_EQUAL && res == val) {
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"matched selector %s(%s) equal to %s",
|
|
Packit |
8480eb |
v->def, v->val, s->comp.value);
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
} else if (s->compare & SEL_COMP_NOTEQUAL && res != val) {
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"matched selector %s(%s) not equal to %s",
|
|
Packit |
8480eb |
v->def, v->val, s->comp.value);
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"did not match selector %s(%s) %s %s",
|
|
Packit |
8480eb |
v->def, v->val,
|
|
Packit |
8480eb |
(s->compare & SEL_COMP_EQUAL ? "==" : "!="),
|
|
Packit |
8480eb |
s->comp.value);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case SEL_FLAG_FUNC1:
|
|
Packit |
8480eb |
if (s->sel->selector != SEL_TRUE &&
|
|
Packit |
8480eb |
s->sel->selector != SEL_FALSE &&
|
|
Packit |
8480eb |
!s->func.arg1) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"expected argument missing for selector %s",
|
|
Packit |
8480eb |
s->sel->name);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (s->sel->selector) {
|
|
Packit |
8480eb |
case SEL_TRUE:
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
if (s->compare == SEL_COMP_NOT)
|
|
Packit |
8480eb |
ret = !ret;
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"matched selector %s(%s)",
|
|
Packit |
8480eb |
s->sel->name, s->func.arg1);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"did not match selector %s(%s)",
|
|
Packit |
8480eb |
s->sel->name, s->func.arg1);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case SEL_FALSE:
|
|
Packit |
8480eb |
if (s->compare == SEL_COMP_NOT)
|
|
Packit |
8480eb |
ret = !ret;
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"matched selector %s(%s)",
|
|
Packit |
8480eb |
s->sel->name, s->func.arg1);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"did not match selector %s(%s)",
|
|
Packit |
8480eb |
s->sel->name, s->func.arg1);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case SEL_XHOST:
|
|
Packit Service |
145c60 |
ret = match_my_name(logopt, s->func.arg1, sv);
|
|
Packit |
8480eb |
if (s->compare == SEL_COMP_NOT)
|
|
Packit |
8480eb |
ret = !ret;
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"matched selector %s(%s) to host name",
|
|
Packit |
8480eb |
s->sel->name, s->func.arg1);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"did not match selector %s(%s) to host name",
|
|
Packit |
8480eb |
s->sel->name, s->func.arg1);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case SEL_EXISTS:
|
|
Packit Service |
145c60 |
/* Sould be OK to fail on any error here */
|
|
Packit Service |
145c60 |
ret = !lstat(s->func.arg1, &st);
|
|
Packit Service |
145c60 |
if (s->compare == SEL_COMP_NOT)
|
|
Packit Service |
145c60 |
ret = !ret;
|
|
Packit Service |
145c60 |
if (ret)
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"matched selector %s(%s)",
|
|
Packit Service |
145c60 |
s->sel->name, s->func.arg1);
|
|
Packit Service |
145c60 |
else
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"did not match selector %s(%s)",
|
|
Packit Service |
145c60 |
s->sel->name, s->func.arg1);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case SEL_IN_NETWORK:
|
|
Packit Service |
145c60 |
ret = in_network(s->func.arg1);
|
|
Packit Service |
145c60 |
if (s->compare == SEL_COMP_NOT)
|
|
Packit Service |
145c60 |
ret = !ret;
|
|
Packit Service |
145c60 |
if (ret)
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"matched selector %s(%s)",
|
|
Packit Service |
145c60 |
s->sel->name, s->func.arg1);
|
|
Packit Service |
145c60 |
else
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"did not match selector %s(%s)",
|
|
Packit Service |
145c60 |
s->sel->name, s->func.arg1);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case SEL_FLAG_FUNC2:
|
|
Packit |
8480eb |
if (!s->func.arg1) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"expected argument missing for selector %s",
|
|
Packit |
8480eb |
s->sel->name);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (s->sel->selector) {
|
|
Packit |
8480eb |
case SEL_NETGRP:
|
|
Packit |
8480eb |
case SEL_NETGRPD:
|
|
Packit Service |
145c60 |
if (s->func.arg2)
|
|
Packit Service |
145c60 |
host = s->func.arg2;
|
|
Packit Service |
145c60 |
else {
|
|
Packit Service |
145c60 |
if (s->sel->selector == SEL_NETGRP)
|
|
Packit Service |
145c60 |
v = macro_findvar(sv, "host", 4);
|
|
Packit Service |
145c60 |
else
|
|
Packit Service |
145c60 |
v = macro_findvar(sv, "hostd", 5);
|
|
Packit Service |
145c60 |
if (!v || !*v->val) {
|
|
Packit Service |
145c60 |
error(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"failed to get value of ${host}");
|
|
Packit Service |
145c60 |
break;
|
|
Packit Service |
145c60 |
}
|
|
Packit Service |
145c60 |
host = v->val;
|
|
Packit Service |
145c60 |
}
|
|
Packit Service |
145c60 |
ret = innetgr(s->func.arg1, host, NULL, NULL);
|
|
Packit Service |
145c60 |
if (s->compare == SEL_COMP_NOT)
|
|
Packit Service |
145c60 |
ret = !ret;
|
|
Packit Service |
145c60 |
if (ret) {
|
|
Packit Service |
145c60 |
if (!s->func.arg2)
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"matched selector %s(%s)",
|
|
Packit Service |
145c60 |
s->sel->name, s->func.arg1);
|
|
Packit Service |
145c60 |
else
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"matched selector %s(%s,%s)",
|
|
Packit Service |
145c60 |
s->sel->name, s->func.arg1,
|
|
Packit Service |
145c60 |
s->func.arg2);
|
|
Packit Service |
145c60 |
} else {
|
|
Packit Service |
145c60 |
if (!s->func.arg2)
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"did not match selector %s(%s)",
|
|
Packit Service |
145c60 |
s->sel->name, s->func.arg1);
|
|
Packit Service |
145c60 |
else
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"did not match selector %s(%s,%s)",
|
|
Packit Service |
145c60 |
s->sel->name, s->func.arg1, s->func.arg2);
|
|
Packit Service |
145c60 |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void update_with_defaults(struct amd_entry *defaults,
|
|
Packit |
8480eb |
struct amd_entry *entry,
|
|
Packit |
8480eb |
struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
const struct substvar *v;
|
|
Packit |
8480eb |
unsigned long fstype = entry->flags & AMD_MOUNT_TYPE_MASK;
|
|
Packit |
8480eb |
char *tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (fstype == AMD_MOUNT_TYPE_NONE) {
|
|
Packit |
8480eb |
unsigned long deftype = defaults->flags & AMD_MOUNT_TYPE_MASK;
|
|
Packit |
8480eb |
if (deftype != AMD_MOUNT_TYPE_NONE)
|
|
Packit |
8480eb |
entry->flags |= (defaults->flags & AMD_MOUNT_TYPE_MASK);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
entry->flags = AMD_MOUNT_TYPE_NFS;
|
|
Packit |
8480eb |
tmp = strdup("nfs");
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->type = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->type && defaults->type) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->type);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->type = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->map_type && defaults->map_type) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->map_type);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->map_type = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->pref && defaults->pref) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->pref);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->pref = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->fs) {
|
|
Packit |
8480eb |
if (defaults->fs) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->fs);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->fs = tmp;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
v = macro_findvar(sv, "fs", 2);
|
|
Packit |
8480eb |
if (v)
|
|
Packit |
8480eb |
entry->fs = strdup(v->val);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->rfs) {
|
|
Packit |
8480eb |
if (defaults->rfs) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->rfs);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->rfs = tmp;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
v = macro_findvar(sv, "rfs", 3);
|
|
Packit |
8480eb |
if (v)
|
|
Packit |
8480eb |
entry->rfs = strdup(v->val);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->rhost) {
|
|
Packit |
8480eb |
if (defaults->rhost) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->rhost);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->rhost = tmp;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
v = macro_findvar(sv, "host", 4);
|
|
Packit |
8480eb |
if (v)
|
|
Packit |
8480eb |
entry->rhost = strdup(v->val);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->dev && defaults->dev) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->dev);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->dev = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->opts && defaults->opts) {
|
|
Packit |
8480eb |
tmp = merge_options(defaults->opts, entry->opts);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->opts = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->addopts && defaults->addopts) {
|
|
Packit |
8480eb |
tmp = merge_options(defaults->addopts, entry->addopts);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->addopts = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->remopts) {
|
|
Packit |
8480eb |
if (defaults->remopts) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->remopts);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->remopts = tmp;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
v = macro_findvar(sv, "remopts", 7);
|
|
Packit |
8480eb |
if (v)
|
|
Packit |
8480eb |
entry->remopts = strdup(v->val);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *normalize_hostname(unsigned int logopt, const char *host,
|
|
Packit |
8480eb |
unsigned int flags, struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct addrinfo hints, *ni;
|
|
Packit |
8480eb |
char *name;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!(flags & CONF_NORMALIZE_HOSTNAMES))
|
|
Packit |
8480eb |
name = strdup(host);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
memset(&hints, 0, sizeof(hints));
|
|
Packit |
8480eb |
hints.ai_flags = AI_CANONNAME;
|
|
Packit |
8480eb |
hints.ai_family = AF_UNSPEC;
|
|
Packit |
8480eb |
hints.ai_socktype = SOCK_DGRAM;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = getaddrinfo(host, NULL, &hints, &ni);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"hostname lookup failed: %s", gai_strerror(ret));
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
name = strdup(ni->ai_canonname);
|
|
Packit |
8480eb |
freeaddrinfo(ni);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!name)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (flags & CONF_DOMAIN_STRIP) {
|
|
Packit |
8480eb |
const struct substvar *v = macro_findvar(sv, "hostd", 5);
|
|
Packit |
8480eb |
if (v) {
|
|
Packit |
8480eb |
char *d1 = strchr(name, '.');
|
|
Packit |
8480eb |
if (d1) {
|
|
Packit |
8480eb |
char *d2 = strchr(v->val, '.');
|
|
Packit |
8480eb |
if (d2 && !strcmp(d1, d2))
|
|
Packit |
8480eb |
*d1 = '\0';
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return name;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct substvar *expand_entry(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct amd_entry *entry,
|
|
Packit |
8480eb |
unsigned int flags,
|
|
Packit |
8480eb |
struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned int logopt = ap->logopt;
|
|
Packit |
8480eb |
char *expand;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->rhost && *entry->rhost) {
|
|
Packit |
8480eb |
char *host = strdup(entry->rhost);
|
|
Packit |
8480eb |
char *nn;
|
|
Packit |
8480eb |
if (!host) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to allocate storage for rhost");
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (expand_selectors(ap, host, &expand, sv)) {
|
|
Packit |
8480eb |
free(host);
|
|
Packit |
8480eb |
host = expand;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
nn = normalize_hostname(ap->logopt, host, flags, sv);
|
|
Packit |
8480eb |
if (!nn)
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "rhost", 5, host);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "rhost", 5, nn);
|
|
Packit |
8480eb |
free(host);
|
|
Packit |
8480eb |
host = nn;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"rhost expand(\"%s\") -> %s", entry->rhost, host);
|
|
Packit |
8480eb |
free(entry->rhost);
|
|
Packit |
8480eb |
entry->rhost = host;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
next:
|
|
Packit |
8480eb |
if (entry->sublink) {
|
|
Packit |
8480eb |
if (expand_selectors(ap, entry->sublink, &expand, sv)) {
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"sublink expand(\"%s\") -> %s",
|
|
Packit |
8480eb |
entry->sublink, expand);
|
|
Packit |
8480eb |
free(entry->sublink);
|
|
Packit |
8480eb |
entry->sublink = expand;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "sublink", 7, entry->sublink);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->rfs && *entry->rfs) {
|
|
Packit |
8480eb |
if (expand_selectors(ap, entry->rfs, &expand, sv)) {
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"rfs expand(\"%s\") -> %s", entry->rfs, expand);
|
|
Packit |
8480eb |
free(entry->rfs);
|
|
Packit |
8480eb |
entry->rfs = expand;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "rfs", 3, entry->rfs);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->fs && *entry->fs) {
|
|
Packit |
8480eb |
if (expand_selectors(ap, entry->fs, &expand, sv)) {
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"fs expand(\"%s\") -> %s", entry->fs, expand);
|
|
Packit |
8480eb |
free(entry->fs);
|
|
Packit |
8480eb |
entry->fs = expand;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "fs", 2, entry->fs);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->opts && *entry->opts) {
|
|
Packit |
8480eb |
if (expand_selectors(ap, entry->opts, &expand, sv)) {
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"ops expand(\"%s\") -> %s", entry->opts, expand);
|
|
Packit |
8480eb |
free(entry->opts);
|
|
Packit |
8480eb |
entry->opts = expand;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "opts", 4, entry->opts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->addopts && *entry->addopts) {
|
|
Packit |
8480eb |
if (expand_selectors(ap, entry->addopts, &expand, sv)) {
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"addopts expand(\"%s\") -> %s",
|
|
Packit |
8480eb |
entry->addopts, expand);
|
|
Packit |
8480eb |
free(entry->addopts);
|
|
Packit |
8480eb |
entry->addopts = expand;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "addopts", 7, entry->addopts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->remopts && *entry->remopts) {
|
|
Packit |
8480eb |
if (expand_selectors(ap, entry->remopts, &expand, sv)) {
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"remopts expand(\"%s\") -> %s",
|
|
Packit |
8480eb |
entry->remopts, expand);
|
|
Packit |
8480eb |
free(entry->remopts);
|
|
Packit |
8480eb |
entry->remopts = expand;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "remopts", 7, entry->remopts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->mount) {
|
|
Packit |
8480eb |
if (!expand_selectors(ap, entry->mount, &expand, sv)) {
|
|
Packit |
8480eb |
free(entry->mount);
|
|
Packit |
8480eb |
if (entry->umount)
|
|
Packit |
8480eb |
free(entry->umount);
|
|
Packit |
8480eb |
entry->mount = NULL;
|
|
Packit |
8480eb |
entry->umount = NULL;
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"mount expand(\"%s\") -> %s", entry->mount, expand);
|
|
Packit |
8480eb |
free(entry->mount);
|
|
Packit |
8480eb |
entry->mount = expand;
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "mount", 5, entry->mount);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->umount) {
|
|
Packit |
8480eb |
if (!expand_selectors(ap, entry->umount, &expand, sv)) {
|
|
Packit |
8480eb |
free(entry->umount);
|
|
Packit |
8480eb |
entry->umount = NULL;
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"umount expand(\"%s\") -> %s", entry->umount, expand);
|
|
Packit |
8480eb |
free(entry->umount);
|
|
Packit |
8480eb |
entry->umount = expand;
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "umount", 5, entry->umount);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
return sv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void expand_merge_options(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct amd_entry *entry,
|
|
Packit |
8480eb |
struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->opts && *entry->opts) {
|
|
Packit |
8480eb |
if (!expand_selectors(ap, entry->opts, &tmp, sv))
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "failed to expand opts");
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
free(entry->opts);
|
|
Packit |
8480eb |
entry->opts = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->addopts && *entry->addopts) {
|
|
Packit |
8480eb |
if (!expand_selectors(ap, entry->addopts, &tmp, sv))
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "failed to expand addopts");
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
free(entry->addopts);
|
|
Packit |
8480eb |
entry->addopts = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->remopts && *entry->remopts) {
|
|
Packit |
8480eb |
if (!expand_selectors(ap, entry->remopts, &tmp, sv))
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "failed to expand remopts");
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
free(entry->remopts);
|
|
Packit |
8480eb |
entry->remopts = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct substvar *merge_entry_options(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct amd_entry *entry,
|
|
Packit |
8480eb |
struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->addopts)
|
|
Packit |
8480eb |
return sv;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->opts && entry->remopts &&
|
|
Packit |
8480eb |
!strcmp(entry->opts, entry->remopts)) {
|
|
Packit |
8480eb |
expand_merge_options(ap, entry, sv);
|
|
Packit |
8480eb |
tmp = merge_options(entry->opts, entry->addopts);
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
info(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"merge remopts \"%s\" addopts \"%s\" => \"%s\"",
|
|
Packit |
8480eb |
entry->opts, entry->addopts, tmp);
|
|
Packit |
8480eb |
free(entry->opts);
|
|
Packit |
8480eb |
entry->opts = tmp;
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "opts", 4, entry->opts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (*entry->opts) {
|
|
Packit |
8480eb |
tmp = strdup(entry->opts);
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
free(entry->remopts);
|
|
Packit |
8480eb |
entry->remopts = tmp;
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "remopts", 7, entry->remopts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return sv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
expand_merge_options(ap, entry, sv);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->opts && entry->addopts) {
|
|
Packit |
8480eb |
tmp = merge_options(entry->opts, entry->addopts);
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
info(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"merge opts \"%s\" addopts \"%s\" => \"%s\"",
|
|
Packit |
8480eb |
entry->opts, entry->addopts, tmp);
|
|
Packit |
8480eb |
free(entry->opts);
|
|
Packit |
8480eb |
entry->opts = tmp;
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "opts", 4, entry->opts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else if (entry->addopts && *entry->addopts) {
|
|
Packit |
8480eb |
tmp = strdup(entry->addopts);
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
info(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"opts add addopts \"%s\" => \"%s\"", entry->addopts, tmp);
|
|
Packit |
8480eb |
entry->opts = tmp;
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "opts", 4, entry->opts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
expand_merge_options(ap, entry, sv);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->remopts && entry->addopts) {
|
|
Packit |
8480eb |
tmp = merge_options(entry->remopts, entry->addopts);
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
info(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"merge remopts \"%s\" addopts \"%s\" => \"%s\"",
|
|
Packit |
8480eb |
entry->remopts, entry->addopts, tmp);
|
|
Packit |
8480eb |
free(entry->remopts);
|
|
Packit |
8480eb |
entry->remopts = tmp;
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "remopts", 7, entry->remopts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else if (entry->addopts && *entry->addopts) {
|
|
Packit |
8480eb |
tmp = strdup(entry->addopts);
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
info(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"remopts add addopts \"%s\" => \"%s\"",
|
|
Packit |
8480eb |
entry->addopts, tmp);
|
|
Packit |
8480eb |
entry->remopts = tmp;
|
|
Packit |
8480eb |
sv = macro_addvar(sv, "remopts", 7, entry->remopts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return sv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_auto_mount(struct autofs_point *ap, const char *name,
|
|
Packit |
8480eb |
struct amd_entry *entry, unsigned int flags)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char target[PATH_MAX + 1];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->map_type) {
|
|
Packit |
8480eb |
if (strlen(entry->fs) > PATH_MAX) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"error: fs option length is too long");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
strcpy(target, entry->fs);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (strlen(entry->fs) +
|
|
Packit |
8480eb |
strlen(entry->map_type) + 5 > PATH_MAX) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"error: fs + maptype options length is too long");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
strcpy(target, entry->map_type);
|
|
Packit |
8480eb |
strcat(target, ",amd:");
|
|
Packit |
8480eb |
strcat(target, entry->fs);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return do_mount(ap, ap->path,
|
|
Packit |
8480eb |
name, strlen(name), target, "autofs", entry->opts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_link_mount(struct autofs_point *ap, const char *name,
|
|
Packit |
8480eb |
struct amd_entry *entry, unsigned int flags)
|
|
Packit |
8480eb |
{
|
|
Packit Service |
145c60 |
char target[PATH_MAX + 1];
|
|
Packit |
8480eb |
const char *opts = (entry->opts && *entry->opts) ? entry->opts : NULL;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->sublink) {
|
|
Packit |
8480eb |
if (strlen(entry->sublink) > PATH_MAX) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"error: sublink option length is too long");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit Service |
145c60 |
strcpy(target, entry->sublink);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (strlen(entry->fs) > PATH_MAX) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"error: fs option length is too long");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit Service |
145c60 |
strcpy(target, entry->fs);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!(flags & CONF_AUTOFS_USE_LOFS))
|
|
Packit |
8480eb |
goto symlink;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* For a sublink this might cause an external mount */
|
|
Packit |
8480eb |
ret = do_mount(ap, ap->path,
|
|
Packit |
8480eb |
name, strlen(name), target, "bind", opts);
|
|
Packit |
8480eb |
if (!ret)
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX "bind mount failed, symlinking");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
symlink:
|
|
Packit |
8480eb |
ret = do_mount(ap, ap->path,
|
|
Packit |
8480eb |
name, strlen(name), target, "bind", "symlink");
|
|
Packit |
8480eb |
if (!ret)
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to symlink %s to %s", entry->path, target);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->sublink) {
|
|
Packit |
8480eb |
/* failed to complete sublink mount */
|
|
Packit |
8480eb |
umount_amd_ext_mount(ap, entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
out:
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_linkx_mount(struct autofs_point *ap, const char *name,
|
|
Packit |
8480eb |
struct amd_entry *entry, unsigned int flags)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct stat st;
|
|
Packit |
8480eb |
char *target;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->sublink)
|
|
Packit |
8480eb |
target = entry->sublink;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
target = entry->fs;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (lstat(target, &st) < 0)
|
|
Packit |
8480eb |
return errno;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return do_link_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_generic_mount(struct autofs_point *ap, const char *name,
|
|
Packit |
8480eb |
struct amd_entry *entry, const char *target,
|
|
Packit |
8480eb |
unsigned int flags)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
const char *opts = (entry->opts && *entry->opts) ? entry->opts : NULL;
|
|
Packit |
8480eb |
unsigned int umount = 0;
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->fs) {
|
|
Packit |
8480eb |
ret = do_mount(ap, ap->path, name,
|
|
Packit |
8480eb |
strlen(name), target, entry->type, opts);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Careful, external mounts may get mounted
|
|
Packit |
8480eb |
* multiple times since they are outside of
|
|
Packit |
8480eb |
* the automount filesystem.
|
|
Packit |
8480eb |
*/
|
|
Packit Service |
145c60 |
if (!is_mounted(_PATH_MOUNTED, entry->fs, MNTS_REAL)) {
|
|
Packit |
8480eb |
ret = do_mount(ap, entry->fs, "/", 1,
|
|
Packit |
8480eb |
target, entry->type, opts);
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
umount = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
/* We have an external mount */
|
|
Packit Service |
145c60 |
ext_mount_add(&entry->ext_mount, entry->fs, umount);
|
|
Packit |
8480eb |
ret = do_link_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
out:
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_nfs_mount(struct autofs_point *ap, const char *name,
|
|
Packit |
8480eb |
struct amd_entry *entry, unsigned int flags)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char target[PATH_MAX + 1];
|
|
Packit |
8480eb |
unsigned int proximity;
|
|
Packit |
8480eb |
char *opts = (entry->opts && *entry->opts) ? entry->opts : NULL;
|
|
Packit |
8480eb |
unsigned int umount = 0;
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strlen(entry->rhost) + strlen(entry->rfs) + 1 > PATH_MAX) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"error: rhost + rfs options length is too long");
|
|
Packit Service |
145c60 |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(target, entry->rhost);
|
|
Packit |
8480eb |
strcat(target, ":");
|
|
Packit |
8480eb |
strcat(target, entry->rfs);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
proximity = get_network_proximity(entry->rhost);
|
|
Packit |
8480eb |
if (proximity == PROXIMITY_OTHER && entry->remopts && *entry->remopts)
|
|
Packit |
8480eb |
opts = entry->remopts;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->fs) {
|
|
Packit |
8480eb |
ret = mount_nfs->mount_mount(ap, ap->path, name, strlen(name),
|
|
Packit |
8480eb |
target, entry->type, opts,
|
|
Packit |
8480eb |
mount_nfs->context);
|
|
Packit |
8480eb |
} else {
|
|
Packit Service |
145c60 |
if (!is_mounted(_PATH_MOUNTED, entry->fs, MNTS_REAL)) {
|
|
Packit |
8480eb |
ret = mount_nfs->mount_mount(ap, entry->fs, "/", 1,
|
|
Packit |
8480eb |
target, entry->type, opts,
|
|
Packit |
8480eb |
mount_nfs->context);
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
umount = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
/* We might be using an external mount */
|
|
Packit Service |
145c60 |
ext_mount_add(&entry->ext_mount, entry->fs, umount);
|
|
Packit |
8480eb |
ret = do_link_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
out:
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_nfsl_mount(struct autofs_point *ap, const char *name,
|
|
Packit |
8480eb |
struct amd_entry *entry, struct substvar *sv,
|
|
Packit |
8480eb |
unsigned int flags)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
const struct substvar *host, *hostd;
|
|
Packit |
8480eb |
struct stat st;
|
|
Packit |
8480eb |
char *target;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
host = macro_findvar(sv, "host", 4);
|
|
Packit |
8480eb |
if (!host)
|
|
Packit |
8480eb |
return do_nfs_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
hostd = macro_findvar(sv, "hostd", 5);
|
|
Packit |
8480eb |
if (!hostd || !*hostd->val)
|
|
Packit |
8480eb |
return do_nfs_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->sublink)
|
|
Packit |
8480eb |
target = entry->sublink;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
target = entry->fs;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strcasecmp(host->val, entry->rhost) ||
|
|
Packit |
8480eb |
strcasecmp(hostd->val, entry->rhost))
|
|
Packit |
8480eb |
return do_nfs_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
else if (lstat(target, &st) < 0)
|
|
Packit |
8480eb |
return do_nfs_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return do_link_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int wait_for_expire(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_wait_task(ap, ST_EXPIRE, 0);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_mutex_lock();
|
|
Packit |
8480eb |
if (ap->state != ST_SHUTDOWN &&
|
|
Packit |
8480eb |
ap->state != ST_SHUTDOWN_PENDING &&
|
|
Packit |
8480eb |
ap->state != ST_SHUTDOWN_FORCE) {
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
st_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_host_mount(struct autofs_point *ap, const char *name,
|
|
Packit |
8480eb |
struct amd_entry *entry, struct map_source *source,
|
|
Packit |
8480eb |
unsigned int flags)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct lookup_mod *lookup;
|
|
Packit |
8480eb |
struct map_source *instance;
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
const char *argv[2];
|
|
Packit |
8480eb |
const char **pargv = NULL;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
int argc = 0;
|
|
Packit |
8480eb |
int ret = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If the mount point name isn't the same as the host name
|
|
Packit |
8480eb |
* then we need to symlink to it after the mount. Attempt
|
|
Packit |
8480eb |
* the allocation and set entry->path to the base location
|
|
Packit |
8480eb |
* of the hosts mount tree so we can find it in
|
|
Packit |
8480eb |
* lookup_nss_mount() later.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (strcmp(name, entry->rhost)) {
|
|
Packit |
8480eb |
char *target;
|
|
Packit |
8480eb |
size_t len = strlen(ap->path) + strlen(entry->rhost) + 2;
|
|
Packit |
8480eb |
target = malloc(len);
|
|
Packit |
8480eb |
if (!target) {
|
|
Packit |
8480eb |
warn(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to alloc target to hosts mount base");
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
strcpy(target, ap->path);
|
|
Packit |
8480eb |
strcat(target, "/");
|
|
Packit |
8480eb |
strcat(target, entry->rhost);
|
|
Packit |
8480eb |
if (entry->path)
|
|
Packit |
8480eb |
free(entry->path);
|
|
Packit |
8480eb |
entry->path = target;
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Wait for any expire before racing to mount the
|
|
Packit |
8480eb |
* export tree or bail out if we're shutting down.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!wait_for_expire(ap))
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->opts && *entry->opts) {
|
|
Packit |
8480eb |
argv[0] = entry->opts;
|
|
Packit |
8480eb |
argv[1] = NULL;
|
|
Packit |
8480eb |
pargv = argv;
|
|
Packit |
8480eb |
argc = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
instance_mutex_lock();
|
|
Packit |
8480eb |
status = open_lookup("hosts", MODPREFIX, NULL, argc, pargv, &lookup);
|
|
Packit |
8480eb |
if (status != NSS_STATUS_SUCCESS) {
|
|
Packit |
8480eb |
debug(ap->logopt, "open lookup module hosts failed");
|
|
Packit |
8480eb |
instance_mutex_unlock();
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
instance = master_find_source_instance(source,
|
|
Packit |
8480eb |
"hosts", "sun", argc, pargv);
|
|
Packit |
8480eb |
if (!instance) {
|
|
Packit |
8480eb |
instance = master_add_source_instance(source,
|
|
Packit |
8480eb |
"hosts", "sun", monotonic_time(NULL), argc, pargv);
|
|
Packit |
8480eb |
if (!instance) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to create source instance for hosts map");
|
|
Packit |
8480eb |
instance_mutex_unlock();
|
|
Packit |
8480eb |
close_lookup(lookup);
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
instance->lookup = lookup;
|
|
Packit |
8480eb |
instance_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_writelock(source->mc);
|
|
Packit |
8480eb |
me = cache_lookup_distinct(source->mc, name);
|
|
Packit |
8480eb |
if (me)
|
|
Packit |
8480eb |
cache_push_mapent(me, NULL);
|
|
Packit |
8480eb |
cache_unlock(source->mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_current_wait(ap->entry);
|
|
Packit |
8480eb |
ap->entry->current = source;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = lookup->lookup_mount(ap, entry->rhost,
|
|
Packit |
8480eb |
strlen(entry->rhost), lookup->context);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(name, entry->rhost))
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (do_mount(ap, ap->path,
|
|
Packit |
8480eb |
name, strlen(name), entry->path, "bind", "symlink"))
|
|
Packit |
8480eb |
warn(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to create symlink to hosts mount base");
|
|
Packit |
8480eb |
out:
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_program_mount(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct amd_entry *entry, const char *name)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *prog, *str;
|
|
Packit |
8480eb |
char **argv;
|
|
Packit |
8480eb |
int argc = -1;
|
|
Packit |
8480eb |
int rv = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
str = strdup(entry->mount);
|
|
Packit |
8480eb |
if (!str)
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
prog = NULL;
|
|
Packit |
8480eb |
argv = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
argc = construct_argv(str, &prog, &argv);
|
|
Packit |
8480eb |
if (argc == -1) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: error creating mount arguments", entry->type);
|
|
Packit |
8480eb |
free(str);
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* The am-utils documentation doesn't actually say that the
|
|
Packit |
8480eb |
* mount (and umount, if given) command need to use ${fs} as
|
|
Packit |
8480eb |
* the mount point in the command.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* For program mounts there's no way to know what the mount
|
|
Packit |
8480eb |
* point is so ${fs} must be used in the mount (and umount,
|
|
Packit |
8480eb |
* if given) in order to create the mount point directory
|
|
Packit |
8480eb |
* before executing the mount command and removing it at
|
|
Packit |
8480eb |
* umount.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ext_mount_inuse(entry->fs)) {
|
|
Packit |
8480eb |
rv = 0;
|
|
Packit |
8480eb |
ext_mount_add(&entry->ext_mount, entry->fs, 1);
|
|
Packit |
8480eb |
} else {
|
|
Packit Service |
145c60 |
rv = mkdir_path(entry->fs, 0555);
|
|
Packit |
8480eb |
if (rv && errno != EEXIST) {
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
char *estr;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "%s: mkdir_path %s failed: %s",
|
|
Packit |
8480eb |
entry->type, entry->fs, estr);
|
|
Packit |
8480eb |
goto do_free;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rv = spawnv(ap->logopt, prog, (const char * const *) argv);
|
|
Packit |
8480eb |
if (WIFEXITED(rv) && !WEXITSTATUS(rv)) {
|
|
Packit Service |
145c60 |
rv = 0;
|
|
Packit Service |
145c60 |
ext_mount_add(&entry->ext_mount, entry->fs, 1);
|
|
Packit Service |
145c60 |
debug(ap->logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"%s: mounted %s", entry->type, entry->fs);
|
|
Packit Service |
145c60 |
} else {
|
|
Packit Service |
145c60 |
if (!ext_mount_inuse(entry->fs))
|
|
Packit Service |
145c60 |
rmdir_path(ap, entry->fs, ap->dev);
|
|
Packit Service |
145c60 |
error(ap->logopt, MODPREFIX
|
|
Packit Service |
145c60 |
"%s: failed to mount using: %s",
|
|
Packit Service |
145c60 |
entry->type, entry->mount);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
do_free:
|
|
Packit |
8480eb |
free_argv(argc, (const char **) argv);
|
|
Packit |
8480eb |
free(str);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (rv)
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rv = do_link_mount(ap, name, entry, 0);
|
|
Packit |
8480eb |
if (!rv)
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (umount_amd_ext_mount(ap, entry)) {
|
|
Packit |
8480eb |
if (!ext_mount_inuse(entry->fs))
|
|
Packit |
8480eb |
rmdir_path(ap, entry->fs, ap->dev);
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: failed to umount external mount at %s",
|
|
Packit |
8480eb |
entry->type, entry->fs);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
out:
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static unsigned int validate_auto_options(unsigned int logopt,
|
|
Packit |
8480eb |
struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* The amd manual implies all the mount type auto options
|
|
Packit |
8480eb |
* are optional but I don't think there's much point if
|
|
Packit |
8480eb |
* no map is given. If the option has been intentionally
|
|
Packit |
8480eb |
* left blank the mount must be expected to fail so don't
|
|
Packit |
8480eb |
* report the error.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!entry->fs) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: file system not given", entry->type);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
} else if (!*entry->fs)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static unsigned int validate_link_options(unsigned int logopt,
|
|
Packit |
8480eb |
struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
/* fs is the destimation of the link */
|
|
Packit |
8480eb |
return validate_auto_options(logopt, entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static unsigned int validate_nfs_options(unsigned int logopt,
|
|
Packit |
8480eb |
struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Required option rhost will always have a value unless
|
|
Packit |
8480eb |
* it has been intentionally left blank. It is set from
|
|
Packit |
8480eb |
* ${host} if it is found to be NULL earlier in the parsing
|
|
Packit |
8480eb |
* process. Don't report the error if it has been left blank
|
|
Packit |
8480eb |
* or if the fs option has been left blank since the mount is
|
|
Packit |
8480eb |
* expected to fail.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!entry->rfs || !*entry->rfs) {
|
|
Packit |
8480eb |
if (entry->rfs && !*entry->rfs)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
/* Map option fs has been intentionally left blank */
|
|
Packit |
8480eb |
if (entry->fs && !*entry->fs)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
entry->rfs = strdup(entry->fs);
|
|
Packit |
8480eb |
if (!entry->rfs) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: remote file system not given", entry->type);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (entry->sublink && !entry->fs) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: sublink option requires option fs");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static unsigned int validate_generic_options(unsigned int logopt,
|
|
Packit |
8480eb |
unsigned long fstype,
|
|
Packit |
8480eb |
struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If dev or rfs are empty in the map entry the mount is
|
|
Packit |
8480eb |
* expected to fail so don't report the error.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (fstype != AMD_MOUNT_TYPE_LOFS) {
|
|
Packit |
8480eb |
if (!entry->dev) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: mount device not given", entry->type);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
} else if (!*entry->dev)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (!entry->rfs) {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Can't use entry->type as the mount type to reprot
|
|
Packit |
8480eb |
* the error since entry->type == "bind" not "lofs".
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
error(logopt, MODPREFIX "lofs: mount device not given");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
} else if (!*entry->rfs)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (entry->sublink && !entry->fs) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: sublink option requires option fs");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static unsigned int validate_ufs_fstype(unsigned int logopt,
|
|
Packit |
8480eb |
struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
const char *type = (const char *) entry->type;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strcmp(type, "ext") && strcmp(type, "ext2") &&
|
|
Packit |
8480eb |
strcmp(type, "ext3") && strcmp(type, "ext4") &&
|
|
Packit |
8480eb |
strcmp(type, "xfs") && strcmp(type, "jfs")) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: mount type %s not valid as ufs mount type on Linux",
|
|
Packit |
8480eb |
type);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static unsigned int validate_host_options(unsigned int logopt,
|
|
Packit |
8480eb |
struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* rhost is always non-null, unless it is intentionally left
|
|
Packit |
8480eb |
* empty, because it will have the the value of the host name
|
|
Packit |
8480eb |
* if it isn't given in the map entry. Don't report an error
|
|
Packit |
8480eb |
* if it has been left empty since it's expected to fail.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!entry->rhost) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: remote host name not given", entry->type);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
} else if (!*entry->rhost)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static unsigned int validate_program_options(unsigned int logopt,
|
|
Packit |
8480eb |
struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* entry->mount will be NULL if there is a problem expanding
|
|
Packit |
8480eb |
* ${} macros in expandamdent().
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!entry->mount) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: mount program invalid or not set", entry->type);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->fs || !*entry->fs) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"%s: ${fs} must be used as the mount point but is not set",
|
|
Packit |
8480eb |
entry->type);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int amd_mount(struct autofs_point *ap, const char *name,
|
|
Packit |
8480eb |
struct amd_entry *entry, struct map_source *source,
|
|
Packit |
8480eb |
struct substvar *sv, unsigned int flags,
|
|
Packit |
8480eb |
struct parse_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned long fstype = entry->flags & AMD_MOUNT_TYPE_MASK;
|
|
Packit |
8480eb |
int ret = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (fstype) {
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_AUTO:
|
|
Packit |
8480eb |
if (!validate_auto_options(ap->logopt, entry))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
ret = do_auto_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_LOFS:
|
|
Packit |
8480eb |
if (!validate_generic_options(ap->logopt, fstype, entry))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
ret = do_generic_mount(ap, name, entry, entry->rfs, flags);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_UFS:
|
|
Packit |
8480eb |
if (!validate_ufs_fstype(ap->logopt, entry))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
/* fall through to validate generic options */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_EXT:
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_XFS:
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_CDFS:
|
|
Packit |
8480eb |
if (!validate_generic_options(ap->logopt, fstype, entry))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
ret = do_generic_mount(ap, name, entry, entry->dev, flags);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_NFS:
|
|
Packit |
8480eb |
if (!validate_nfs_options(ap->logopt, entry))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
ret = do_nfs_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_NFSL:
|
|
Packit |
8480eb |
if (!validate_nfs_options(ap->logopt, entry) ||
|
|
Packit |
8480eb |
!validate_link_options(ap->logopt, entry))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
ret = do_nfsl_mount(ap, name, entry, sv, flags);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_LINK:
|
|
Packit |
8480eb |
if (!validate_link_options(ap->logopt, entry))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
ret = do_link_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_LINKX:
|
|
Packit |
8480eb |
if (!validate_link_options(ap->logopt, entry))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
ret = do_linkx_mount(ap, name, entry, flags);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_HOST:
|
|
Packit |
8480eb |
if (!validate_host_options(ap->logopt, entry))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
ret = do_host_mount(ap, name, entry, source, flags);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AMD_MOUNT_TYPE_PROGRAM:
|
|
Packit |
8480eb |
if (!validate_program_options(ap->logopt, entry))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
ret = do_program_mount(ap, entry, name);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
info(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "unknown file system type %x", fstype);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void dequote_entry(struct autofs_point *ap, struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *res;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->pref) {
|
|
Packit |
8480eb |
res = dequote(entry->pref, strlen(entry->pref), ap->logopt);
|
|
Packit |
8480eb |
if (res) {
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "pref dequote(\"%.*s\") -> %s",
|
|
Packit |
8480eb |
strlen(entry->pref), entry->pref, res);
|
|
Packit |
8480eb |
free(entry->pref);
|
|
Packit |
8480eb |
entry->pref = res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->sublink) {
|
|
Packit |
8480eb |
res = dequote(entry->sublink, strlen(entry->sublink), ap->logopt);
|
|
Packit |
8480eb |
if (res) {
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "sublink dequote(\"%.*s\") -> %s",
|
|
Packit |
8480eb |
strlen(entry->sublink), entry->sublink, res);
|
|
Packit |
8480eb |
free(entry->sublink);
|
|
Packit |
8480eb |
entry->sublink = res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->fs && *entry->fs) {
|
|
Packit |
8480eb |
res = dequote(entry->fs, strlen(entry->fs), ap->logopt);
|
|
Packit |
8480eb |
if (res) {
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "fs dequote(\"%.*s\") -> %s",
|
|
Packit |
8480eb |
strlen(entry->fs), entry->fs, res);
|
|
Packit |
8480eb |
free(entry->fs);
|
|
Packit |
8480eb |
entry->fs = res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->rfs && *entry->rfs) {
|
|
Packit |
8480eb |
res = dequote(entry->rfs, strlen(entry->rfs), ap->logopt);
|
|
Packit |
8480eb |
if (res) {
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "rfs dequote(\"%.*s\") -> %s",
|
|
Packit |
8480eb |
strlen(entry->rfs), entry->rfs, res);
|
|
Packit |
8480eb |
free(entry->rfs);
|
|
Packit |
8480eb |
entry->rfs = res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->opts && *entry->opts) {
|
|
Packit |
8480eb |
res = dequote(entry->opts, strlen(entry->opts), ap->logopt);
|
|
Packit |
8480eb |
if (res) {
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "ops dequote(\"%.*s\") -> %s",
|
|
Packit |
8480eb |
strlen(entry->opts), entry->opts, res);
|
|
Packit |
8480eb |
free(entry->opts);
|
|
Packit |
8480eb |
entry->opts = res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->remopts && *entry->remopts) {
|
|
Packit |
8480eb |
res = dequote(entry->remopts, strlen(entry->remopts), ap->logopt);
|
|
Packit |
8480eb |
if (res) {
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "remopts dequote(\"%.*s\") -> %s",
|
|
Packit |
8480eb |
strlen(entry->remopts), entry->remopts, res);
|
|
Packit |
8480eb |
free(entry->remopts);
|
|
Packit |
8480eb |
entry->remopts = res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->addopts && *entry->addopts) {
|
|
Packit |
8480eb |
res = dequote(entry->addopts, strlen(entry->addopts), ap->logopt);
|
|
Packit |
8480eb |
if (res) {
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "addopts dequote(\"%.*s\") -> %s",
|
|
Packit |
8480eb |
strlen(entry->addopts), entry->addopts, res);
|
|
Packit |
8480eb |
free(entry->addopts);
|
|
Packit |
8480eb |
entry->addopts = res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void normalize_sublink(unsigned int logopt,
|
|
Packit |
8480eb |
struct amd_entry *entry, struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *new;
|
|
Packit |
8480eb |
size_t len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Normalizing sublink requires a non-blank fs option */
|
|
Packit |
8480eb |
if (!*entry->fs)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->sublink && *entry->sublink != '/') {
|
|
Packit |
8480eb |
len = strlen(entry->fs) + strlen(entry->sublink) + 2;
|
|
Packit |
8480eb |
new = malloc(len);
|
|
Packit |
8480eb |
if (!new) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"error: couldn't allocate storage for sublink");
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
strcpy(new, entry->fs);
|
|
Packit |
8480eb |
strcat(new, "/");
|
|
Packit |
8480eb |
strcat(new, entry->sublink);
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX
|
|
Packit |
8480eb |
"rfs dequote(\"%.*s\") -> %s",
|
|
Packit |
8480eb |
strlen(entry->sublink), entry->sublink, new);
|
|
Packit |
8480eb |
free(entry->sublink);
|
|
Packit |
8480eb |
entry->sublink = new;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Set the prefix.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* This is done in a couple of places, here is as good a place as
|
|
Packit |
8480eb |
* any to describe it.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* If a prefix is present in the map entry then use it.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* A pref option with the value none is required to use no prefix,
|
|
Packit |
8480eb |
* otherwise the prefix of the parent map, if any, will be used.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static void update_prefix(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct amd_entry *entry, const char *name)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
size_t len;
|
|
Packit |
8480eb |
char *new;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->pref && ap->pref) {
|
|
Packit |
8480eb |
len = strlen(ap->pref) + strlen(name) + 2;
|
|
Packit |
8480eb |
new = malloc(len);
|
|
Packit |
8480eb |
if (new) {
|
|
Packit |
8480eb |
strcpy(new, ap->pref);
|
|
Packit |
8480eb |
strcat(new, name);
|
|
Packit |
8480eb |
strcat(new, "/");
|
|
Packit |
8480eb |
entry->pref = new;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Service |
145c60 |
static int match_selectors(unsigned int logopt,
|
|
Packit |
8480eb |
struct amd_entry *entry, struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct selector *s = entry->selector;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* No selectors, always match */
|
|
Packit |
8480eb |
if (!s) {
|
|
Packit Service |
145c60 |
debug(logopt, MODPREFIX "no selectors found in location");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* All selectors must match */
|
|
Packit |
8480eb |
while (s) {
|
|
Packit Service |
145c60 |
ret = eval_selector(logopt, entry, sv);
|
|
Packit |
8480eb |
if (!ret)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
s = s->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (!s)
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct amd_entry *dup_defaults_entry(struct amd_entry *defaults)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct amd_entry *entry;
|
|
Packit |
8480eb |
char *tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry = malloc(sizeof(struct amd_entry));
|
|
Packit |
8480eb |
if (!entry)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
memset(entry, 0, sizeof(struct amd_entry));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry->flags = defaults->flags;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (defaults->type) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->type);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->type = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (defaults->map_type) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->map_type);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->map_type = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (defaults->pref) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->pref);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->pref = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (defaults->fs) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->fs);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->fs = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* These shouldn't be blank in a defaults entry but ... */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (defaults->rfs && *defaults->rfs) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->rfs);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->rfs = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (defaults->rhost && *defaults->rhost) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->rhost);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->rhost = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (defaults->dev && *defaults->dev) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->dev);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->dev = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (defaults->opts && *defaults->opts) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->opts);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->opts = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (defaults->addopts && *defaults->addopts) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->addopts);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->addopts = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (defaults->remopts && *defaults->remopts) {
|
|
Packit |
8480eb |
tmp = strdup(defaults->remopts);
|
|
Packit |
8480eb |
if (tmp)
|
|
Packit |
8480eb |
entry->remopts = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&entry->list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return entry;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct amd_entry *make_default_entry(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *defaults = "opts:=rw,defaults";
|
|
Packit |
8480eb |
struct amd_entry *defaults_entry;
|
|
Packit |
8480eb |
struct list_head dflts;
|
|
Packit |
8480eb |
char *map_type;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&dflts);
|
|
Packit |
8480eb |
if (amd_parse_list(ap, defaults, &dflts, &sv))
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
defaults_entry = list_entry(dflts.next, struct amd_entry, list);
|
|
Packit Service |
145c60 |
list_del_init(&defaults_entry->list);
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If map type isn't given try to inherit from
|
|
Packit |
8480eb |
* parent. A NULL map type is valid and means
|
|
Packit |
8480eb |
* use configured nss sources.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
map_type = conf_amd_get_map_type(ap->path);
|
|
Packit Service |
145c60 |
if (map_type)
|
|
Packit Service |
145c60 |
defaults_entry->map_type = strdup(map_type);
|
|
Packit |
8480eb |
/* The list should now be empty .... */
|
|
Packit |
8480eb |
free_amd_entry_list(&dflts);
|
|
Packit |
8480eb |
return defaults_entry;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct amd_entry *select_default_entry(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct list_head *entries,
|
|
Packit |
8480eb |
struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned long flags = conf_amd_get_flags(ap->path);
|
|
Packit |
8480eb |
struct amd_entry *defaults_entry = NULL;
|
|
Packit |
8480eb |
struct amd_entry *entry_default = NULL;
|
|
Packit |
8480eb |
struct list_head *p, *head;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!(flags & CONF_SELECTORS_IN_DEFAULTS))
|
|
Packit |
8480eb |
goto no_sel;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = entries;
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
struct amd_entry *this = list_entry(p, struct amd_entry, list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (this->flags & AMD_DEFAULTS_MERGE) {
|
|
Packit |
8480eb |
if (entry_default)
|
|
Packit |
8480eb |
free_amd_entry(entry_default);
|
|
Packit |
8480eb |
list_del_init(&this->list);
|
|
Packit |
8480eb |
entry_default = this;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
} else if (this->flags & AMD_DEFAULTS_RESET) {
|
|
Packit |
8480eb |
struct amd_entry *new;
|
|
Packit |
8480eb |
new = dup_defaults_entry(defaults_entry);
|
|
Packit |
8480eb |
if (new) {
|
|
Packit |
8480eb |
free_amd_entry(entry_default);
|
|
Packit |
8480eb |
entry_default = new;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
list_del_init(&this->list);
|
|
Packit |
8480eb |
free_amd_entry(this);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* This probably should be a fail since we expect
|
|
Packit |
8480eb |
* selectors to pick the default entry.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!this->selector)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit Service |
145c60 |
if (match_selectors(ap->logopt, this, sv)) {
|
|
Packit |
8480eb |
if (entry_default) {
|
|
Packit |
8480eb |
/*update_with_defaults(entry_default, this, sv);*/
|
|
Packit |
8480eb |
free_amd_entry(entry_default);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
list_del_init(&this->list);
|
|
Packit |
8480eb |
defaults_entry = this;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Not strickly amd semantics but ... */
|
|
Packit |
8480eb |
if (!defaults_entry && entry_default) {
|
|
Packit |
8480eb |
defaults_entry = entry_default;
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!defaults_entry) {
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"no matching selector(s) found in defaults, "
|
|
Packit |
8480eb |
"using internal defaults");
|
|
Packit |
8480eb |
goto ret_default;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
no_sel:
|
|
Packit |
8480eb |
if (list_empty(entries))
|
|
Packit |
8480eb |
goto ret_default;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
defaults_entry = list_entry(entries->next, struct amd_entry, list);
|
|
Packit |
8480eb |
list_del_init(&defaults_entry->list);
|
|
Packit |
8480eb |
if (!list_empty(entries)) {
|
|
Packit |
8480eb |
free_amd_entry(defaults_entry);
|
|
Packit |
8480eb |
goto ret_default;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
/*merge_entry_options(ap, defaults_entry, sv);*/
|
|
Packit |
8480eb |
/*normalize_sublink(ap->logopt, defaults_entry, sv);*/
|
|
Packit |
8480eb |
return defaults_entry;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret_default:
|
|
Packit |
8480eb |
return make_default_entry(ap, sv);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct amd_entry *get_defaults_entry(struct autofs_point *ap,
|
|
Packit |
8480eb |
const char *defaults,
|
|
Packit |
8480eb |
struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct amd_entry *entry;
|
|
Packit |
8480eb |
struct list_head dflts;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&dflts);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry = NULL;
|
|
Packit |
8480eb |
if (!defaults)
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
char *expand;
|
|
Packit |
8480eb |
if (!expand_selectors(ap, defaults, &expand, sv))
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
if (amd_parse_list(ap, expand, &dflts, &sv)) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to parse defaults entry, "
|
|
Packit |
8480eb |
"attempting to use internal default");
|
|
Packit |
8480eb |
free(expand);
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
entry = select_default_entry(ap, &dflts, sv);
|
|
Packit |
8480eb |
if (!entry->map_type) {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If map type isn't given try to inherit from
|
|
Packit |
8480eb |
* parent. A NULL map type is valid and means
|
|
Packit |
8480eb |
* use configured nss sources.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
char *map_type = conf_amd_get_map_type(ap->path);
|
|
Packit Service |
145c60 |
if (map_type)
|
|
Packit Service |
145c60 |
entry->map_type = strdup(map_type);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
free(expand);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return entry;
|
|
Packit |
8480eb |
out:
|
|
Packit |
8480eb |
return make_default_entry(ap, sv);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct amd_entry *setup_defaults(struct autofs_point *ap,
|
|
Packit |
8480eb |
const char *name, int name_len,
|
|
Packit |
8480eb |
struct map_source *source,
|
|
Packit |
8480eb |
struct substvar **sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct amd_entry *defaults_entry;
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
struct substvar *nsv;
|
|
Packit |
8480eb |
char *defaults;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mc = source->mc;
|
|
Packit |
8480eb |
defaults = NULL;
|
|
Packit |
8480eb |
defaults_entry = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
nsv = add_lookup_vars(ap, name, name_len, source, NULL);
|
|
Packit |
8480eb |
if (!nsv)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
defaults = conf_amd_get_map_defaults(ap->path);
|
|
Packit |
8480eb |
if (defaults) {
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"using map_defaults %s for %s", defaults, ap->path);
|
|
Packit |
8480eb |
} else if ((me = cache_lookup_distinct(mc, "/defaults"))) {
|
|
Packit |
8480eb |
defaults = strdup(me->mapent);
|
|
Packit |
8480eb |
if (defaults)
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"using /defaults %s from map", defaults);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
macro_free_table(nsv);
|
|
Packit |
8480eb |
nsv = NULL;
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
defaults_entry = get_defaults_entry(ap, defaults, nsv);
|
|
Packit |
8480eb |
if (!defaults_entry) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "failed to get a defaults entry");
|
|
Packit |
8480eb |
macro_free_table(nsv);
|
|
Packit |
8480eb |
nsv = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
if (defaults)
|
|
Packit |
8480eb |
free(defaults);
|
|
Packit |
8480eb |
if (*sv)
|
|
Packit |
8480eb |
macro_free_table(*sv);
|
|
Packit |
8480eb |
*sv = nsv;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return defaults_entry;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int parse_mount(struct autofs_point *ap, const char *name,
|
|
Packit |
8480eb |
int name_len, const char *mapent, void *context)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct parse_context *ctxt = (struct parse_context *) context;
|
|
Packit |
8480eb |
unsigned int flags = conf_amd_get_flags(ap->path);
|
|
Packit |
8480eb |
struct substvar *sv = NULL;
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
unsigned int at_least_one;
|
|
Packit |
8480eb |
struct list_head entries, *p, *head;
|
|
Packit |
8480eb |
struct amd_entry *defaults_entry;
|
|
Packit |
8480eb |
struct amd_entry *cur_defaults;
|
|
Packit |
8480eb |
int rv = 1;
|
|
Packit |
8480eb |
int cur_state;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = ap->entry->current;
|
|
Packit |
8480eb |
ap->entry->current = NULL;
|
|
Packit |
8480eb |
master_source_current_signal(ap->entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!mapent) {
|
|
Packit |
8480eb |
warn(ap->logopt, MODPREFIX "error: empty map entry");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&entries);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
defaults_entry = setup_defaults(ap, name, name_len, source, &sv;;
|
|
Packit |
8480eb |
if (!defaults_entry) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to setup defaults entry");
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = amd_parse_list(ap, mapent, &entries, &sv;;
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "failed to parse entry: %s", mapent);
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (list_empty(&entries)) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "no location found after parse");
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cur_defaults = dup_defaults_entry(defaults_entry);
|
|
Packit |
8480eb |
if (!cur_defaults) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to duplicate defaults entry");
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
at_least_one = 0;
|
|
Packit |
8480eb |
head = &entries;
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
struct amd_entry *this = list_entry(p, struct amd_entry, list);
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (this->flags & AMD_DEFAULTS_MERGE) {
|
|
Packit |
8480eb |
free_amd_entry(cur_defaults);
|
|
Packit |
8480eb |
list_del_init(&this->list);
|
|
Packit |
8480eb |
cur_defaults = this;
|
|
Packit |
8480eb |
update_with_defaults(defaults_entry, cur_defaults, sv);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
} else if (this->flags & AMD_DEFAULTS_RESET) {
|
|
Packit |
8480eb |
struct amd_entry *nd, *new;
|
|
Packit |
8480eb |
struct substvar *nsv = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
nd = setup_defaults(ap, name, name_len, source, &nsv;;
|
|
Packit |
8480eb |
if (nd) {
|
|
Packit |
8480eb |
free_amd_entry(defaults_entry);
|
|
Packit |
8480eb |
defaults_entry = nd;
|
|
Packit |
8480eb |
macro_free_table(sv);
|
|
Packit |
8480eb |
sv = nsv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
new = dup_defaults_entry(defaults_entry);
|
|
Packit |
8480eb |
if (new) {
|
|
Packit |
8480eb |
free_amd_entry(cur_defaults);
|
|
Packit |
8480eb |
cur_defaults = new;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
list_del_init(&this->list);
|
|
Packit |
8480eb |
free_amd_entry(this);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "expand defaults entry");
|
|
Packit |
8480eb |
sv = expand_entry(ap, cur_defaults, flags, sv);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (this->flags & AMD_ENTRY_CUT && at_least_one) {
|
|
Packit |
8480eb |
info(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"at least one entry tried before cut selector, "
|
|
Packit |
8480eb |
"not continuing");
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Service |
145c60 |
if (!match_selectors(ap->logopt, this, sv))
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
at_least_one = 1;
|
|
Packit |
8480eb |
|
|
Packit Service |
19c1f8 |
debug(ap->logopt, "expand mount entry");
|
|
Packit Service |
145c60 |
update_with_defaults(cur_defaults, this, sv);
|
|
Packit |
8480eb |
sv = expand_entry(ap, this, flags, sv);
|
|
Packit |
8480eb |
sv = merge_entry_options(ap, this, sv);
|
|
Packit |
8480eb |
normalize_sublink(ap->logopt, this, sv);
|
|
Packit |
8480eb |
update_prefix(ap, this, name);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
dequote_entry(ap, this);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Type "auto" needs to set the prefix at mount time so
|
|
Packit |
8480eb |
* add parsed entry to parent amd mount list and remove
|
|
Packit |
8480eb |
* on mount fail.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
list_add_tail(&this->entries, &ap->amdmounts);
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rv = amd_mount(ap, name, this, source, sv, flags, ctxt);
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
if (!rv) {
|
|
Packit |
8480eb |
/* Mounted, remove entry from parsed list */
|
|
Packit |
8480eb |
list_del_init(&this->list);
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
/* Not mounted, remove entry from the parent list */
|
|
Packit |
8480eb |
list_del_init(&this->entries);
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
free_amd_entry(cur_defaults);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (rv)
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"no more locations to try, returning fail");
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
free_amd_entry_list(&entries);
|
|
Packit |
8480eb |
free_amd_entry(defaults_entry);
|
|
Packit |
8480eb |
macro_free_table(sv);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int parse_done(void *context)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int rv = 0;
|
|
Packit |
8480eb |
struct parse_context *ctxt = (struct parse_context *) context;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
instance_mutex_lock();
|
|
Packit |
8480eb |
if (--init_ctr == 0) {
|
|
Packit |
8480eb |
rv = close_mount(mount_nfs);
|
|
Packit |
8480eb |
mount_nfs = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
instance_mutex_unlock();
|
|
Packit |
8480eb |
if (ctxt)
|
|
Packit |
8480eb |
kill_context(ctxt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|