|
Packit |
8480eb |
/* ----------------------------------------------------------------------- *
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* parse_sun.c - module for Linux automountd to parse a Sun-format
|
|
Packit |
8480eb |
* automounter map
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Copyright 1997 Transmeta Corporation - All Rights Reserved
|
|
Packit |
8480eb |
* Copyright 2000 Jeremy Fitzhardinge <jeremy@goop.org>
|
|
Packit |
8480eb |
* Copyright 2004, 2005 Ian Kent <raven@themaw.net>
|
|
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 |
|
|
Packit |
8480eb |
#define MODPREFIX "parse(sun): "
|
|
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 |
int slashify_colons; /* Change colons to slashes? */
|
|
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 |
1 /* Do slashify_colons */
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int destroy_logpri_fifo(struct autofs_point *ap);
|
|
Packit |
8480eb |
static char *concat_options(char *left, char *right);
|
|
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 |
/*
|
|
Packit |
8480eb |
* $- and &-expand a Sun-style map entry and return the length of the entry.
|
|
Packit |
8480eb |
* If "dst" is NULL, just count the length.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
int expandsunent(const char *src, char *dst, const char *key,
|
|
Packit |
8480eb |
const struct substvar *svc, int slashify_colons)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
const struct substvar *sv;
|
|
Packit |
8480eb |
int len, l, seen_colons;
|
|
Packit |
8480eb |
const char *p;
|
|
Packit |
8480eb |
char ch;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = 0;
|
|
Packit |
8480eb |
seen_colons = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((ch = *src++)) {
|
|
Packit |
8480eb |
switch (ch) {
|
|
Packit |
8480eb |
case '&':
|
|
Packit |
8480eb |
l = strlen(key);
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* In order to ensure that any isspace() characters
|
|
Packit |
8480eb |
* in the key are preserved, we need to escape them
|
|
Packit |
8480eb |
* here.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
const char *keyp = key;
|
|
Packit |
8480eb |
while (*keyp) {
|
|
Packit |
8480eb |
if (isspace(*keyp)) {
|
|
Packit |
8480eb |
if (dst) {
|
|
Packit |
8480eb |
*dst++ = '\\';
|
|
Packit |
8480eb |
*dst++ = *keyp++;
|
|
Packit |
8480eb |
} else
|
|
Packit |
8480eb |
keyp++;
|
|
Packit |
8480eb |
l++;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst++ = *keyp++;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
keyp++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
len += l;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case '$':
|
|
Packit |
8480eb |
if (*src == '{') {
|
|
Packit |
8480eb |
p = strchr(++src, '}');
|
|
Packit |
8480eb |
if (!p) {
|
|
Packit |
8480eb |
/* Ignore rest of string */
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst = '\0';
|
|
Packit |
8480eb |
return len;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
sv = macro_findvar(svc, src, p - src);
|
|
Packit |
8480eb |
if (sv) {
|
|
Packit |
8480eb |
l = strlen(sv->val);
|
|
Packit |
8480eb |
if (dst) {
|
|
Packit |
8480eb |
strcpy(dst, sv->val);
|
|
Packit |
8480eb |
dst += l;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
len += l;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
src = p + 1;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
p = src;
|
|
Packit |
8480eb |
while (isalnum(*p) || *p == '_')
|
|
Packit |
8480eb |
p++;
|
|
Packit |
8480eb |
sv = macro_findvar(svc, src, p - src);
|
|
Packit |
8480eb |
if (sv) {
|
|
Packit |
8480eb |
l = strlen(sv->val);
|
|
Packit |
8480eb |
if (dst) {
|
|
Packit |
8480eb |
strcpy(dst, sv->val);
|
|
Packit |
8480eb |
dst += l;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
len += l;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
src = p;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case '\\':
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst++ = ch;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*src) {
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst++ = *src;
|
|
Packit |
8480eb |
src++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case '"':
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst++ = ch;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (*src && *src != '"') {
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst++ = *src;
|
|
Packit |
8480eb |
src++;
|
|
Packit |
8480eb |
}
|
|
Packit Service |
42268b |
if (*src && dst) {
|
|
Packit |
8480eb |
len++;
|
|
Packit Service |
42268b |
*dst++ = *src++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case ':':
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*(dst++) =
|
|
Packit |
8480eb |
(seen_colons && slashify_colons) ? '/' : ':';
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
/* Were looking for the colon preceeding a path */
|
|
Packit |
8480eb |
if (*src == '/')
|
|
Packit |
8480eb |
seen_colons = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
if (isspace(ch))
|
|
Packit |
8480eb |
seen_colons = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*(dst++) = ch;
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst = '\0';
|
|
Packit |
8480eb |
return len;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_init(int argc, const char *const *argv, struct parse_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *noptstr, *def, *val, *macros, *gbl_options;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
int optlen, len, offset;
|
|
Packit |
8480eb |
const char *xopt;
|
|
Packit |
8480eb |
int i, bval;
|
|
Packit |
8480eb |
unsigned int append_options;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
optlen = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Look for options and capture, and create new defines if we need to */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (i = 0; i < argc; i++) {
|
|
Packit |
8480eb |
if (argv[i][0] == '-' &&
|
|
Packit |
8480eb |
(argv[i][1] == 'D' || argv[i][1] == '-') ) {
|
|
Packit |
8480eb |
switch (argv[i][1]) {
|
|
Packit |
8480eb |
case 'D':
|
|
Packit |
8480eb |
if (argv[i][2])
|
|
Packit |
8480eb |
def = strdup(argv[i] + 2);
|
|
Packit |
8480eb |
else if (++i < argc)
|
|
Packit |
8480eb |
def = strdup(argv[i]);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!def) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "strdup: %s", estr);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
val = strchr(def, '=');
|
|
Packit |
8480eb |
if (val)
|
|
Packit |
8480eb |
*(val++) = '\0';
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
val = "";
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
macro_lock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ctxt->subst = macro_addvar(ctxt->subst,
|
|
Packit |
8480eb |
def, strlen(def), val);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
macro_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* we use 5 for the "-D", "=", "," and the null */
|
|
Packit |
8480eb |
if (ctxt->macros) {
|
|
Packit |
8480eb |
len = strlen(ctxt->macros) + strlen(def) + strlen(val);
|
|
Packit |
8480eb |
macros = realloc(ctxt->macros, len + 5);
|
|
Packit |
8480eb |
if (!macros) {
|
|
Packit |
8480eb |
free(def);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
strcat(macros, ",");
|
|
Packit |
8480eb |
} else { /* No comma, so only +4 */
|
|
Packit |
8480eb |
len = strlen(def) + strlen(val);
|
|
Packit |
8480eb |
macros = malloc(len + 4);
|
|
Packit |
8480eb |
if (!macros) {
|
|
Packit |
8480eb |
free(def);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
*macros = '\0';
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
ctxt->macros = macros;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcat(ctxt->macros, "-D");
|
|
Packit |
8480eb |
strcat(ctxt->macros, def);
|
|
Packit |
8480eb |
strcat(ctxt->macros, "=");
|
|
Packit |
8480eb |
strcat(ctxt->macros, val);
|
|
Packit |
8480eb |
free(def);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case '-':
|
|
Packit |
8480eb |
if (!strncmp(argv[i] + 2, "no-", 3)) {
|
|
Packit |
8480eb |
xopt = argv[i] + 5;
|
|
Packit |
8480eb |
bval = 0;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
xopt = argv[i] + 2;
|
|
Packit |
8480eb |
bval = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strmcmp(xopt, "slashify-colons", 1))
|
|
Packit |
8480eb |
ctxt->slashify_colons = bval;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
error(LOGOPT_ANY,
|
|
Packit |
8480eb |
MODPREFIX "unknown option: %s",
|
|
Packit |
8480eb |
argv[i]);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
error(LOGOPT_ANY,
|
|
Packit |
8480eb |
MODPREFIX "unknown option: %s", argv[i]);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
offset = (argv[i][0] == '-' ? 1 : 0);
|
|
Packit |
8480eb |
len = strlen(argv[i] + offset);
|
|
Packit |
8480eb |
if (ctxt->optstr) {
|
|
Packit |
8480eb |
noptstr =
|
|
Packit |
8480eb |
(char *) realloc(ctxt->optstr, optlen + len + 2);
|
|
Packit |
8480eb |
if (noptstr) {
|
|
Packit |
8480eb |
noptstr[optlen] = ',';
|
|
Packit |
8480eb |
strcpy(noptstr + optlen + 1, argv[i] + offset);
|
|
Packit |
8480eb |
optlen += len + 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
noptstr = (char *) malloc(len + 1);
|
|
Packit |
8480eb |
if (noptstr) {
|
|
Packit |
8480eb |
strcpy(noptstr, argv[i] + offset);
|
|
Packit |
8480eb |
optlen = len;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (!noptstr) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "%s", estr);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
ctxt->optstr = noptstr;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
gbl_options = NULL;
|
|
Packit |
8480eb |
if (global_options) {
|
|
Packit |
8480eb |
if (ctxt->optstr && strstr(ctxt->optstr, global_options))
|
|
Packit |
8480eb |
goto options_done;
|
|
Packit |
8480eb |
gbl_options = strdup(global_options);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (gbl_options) {
|
|
Packit |
8480eb |
append_options = defaults_get_append_options();
|
|
Packit |
8480eb |
if (append_options) {
|
|
Packit |
8480eb |
char *tmp = concat_options(gbl_options, ctxt->optstr);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "concat_options: %s", estr);
|
|
Packit |
8480eb |
free(gbl_options);
|
|
Packit |
8480eb |
} else
|
|
Packit |
8480eb |
ctxt->optstr = tmp;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (!ctxt->optstr)
|
|
Packit |
8480eb |
ctxt->optstr = gbl_options;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
free(gbl_options);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
options_done:
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(LOGOPT_NONE,
|
|
Packit |
8480eb |
MODPREFIX "init gathered global options: %s", ctxt->optstr);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
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 |
*context = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Set up context and escape chain */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ctxt = (struct parse_context *) malloc(sizeof(struct parse_context));
|
|
Packit |
8480eb |
if (!ctxt) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*ctxt = default_context;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (do_init(argc, argv, ctxt)) {
|
|
Packit |
8480eb |
free(ctxt);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
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 |
instance_mutex_unlock();
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
instance_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*context = (void *) ctxt;
|
|
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 |
struct parse_context *ctxt = (struct parse_context *) *context;
|
|
Packit |
8480eb |
struct parse_context *new;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
new = (struct parse_context *) malloc(sizeof(struct parse_context));
|
|
Packit |
8480eb |
if (!new) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*new = default_context;
|
|
Packit |
8480eb |
|
|
Packit Service |
0f11ce |
if (do_init(argc, argv, new)) {
|
|
Packit Service |
0f11ce |
free(new);
|
|
Packit |
8480eb |
return 1;
|
|
Packit Service |
0f11ce |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
kill_context(ctxt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*context = (void *) new;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static const char *parse_options(const char *str, char **ret, unsigned int logopt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
const char *cp = str;
|
|
Packit |
8480eb |
int len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*cp++ != '-')
|
|
Packit |
8480eb |
return str;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*ret != NULL)
|
|
Packit |
8480eb |
free(*ret);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = chunklen(cp, 0);
|
|
Packit |
8480eb |
*ret = dequote(cp, len, logopt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return cp + len;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *concat_options(char *left, char *right)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
char *ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (left == NULL || *left == '\0') {
|
|
Packit |
8480eb |
ret = strdup(right);
|
|
Packit |
8480eb |
free(right);
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (right == NULL || *right == '\0') {
|
|
Packit |
8480eb |
ret = strdup(left);
|
|
Packit |
8480eb |
free(left);
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = malloc(strlen(left) + strlen(right) + 2);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret == NULL) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(ret, left);
|
|
Packit |
8480eb |
strcat(ret, ",");
|
|
Packit |
8480eb |
strcat(ret, right);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(left);
|
|
Packit |
8480eb |
free(right);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int sun_mount(struct autofs_point *ap, const char *root,
|
|
Packit |
8480eb |
const char *name, int namelen,
|
|
Packit |
8480eb |
const char *loc, int loclen, const char *options,
|
|
Packit |
8480eb |
struct parse_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *fstype = "nfs"; /* Default filesystem type */
|
|
Packit |
8480eb |
int nonstrict = 1;
|
|
Packit |
8480eb |
int use_weight_only = ap->flags & MOUNT_FLAG_USE_WEIGHT_ONLY;
|
|
Packit |
8480eb |
int rv, cur_state;
|
|
Packit |
8480eb |
char *mountpoint;
|
|
Packit |
8480eb |
char *what;
|
|
Packit |
8480eb |
char *type;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*options == '\0')
|
|
Packit |
8480eb |
options = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (options) {
|
|
Packit |
8480eb |
char *noptions;
|
|
Packit |
8480eb |
const char *comma;
|
|
Packit |
8480eb |
char *np;
|
|
Packit |
8480eb |
int len = strlen(options) + 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
noptions = np = alloca(len);
|
|
Packit |
8480eb |
*np = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Extract fstype= pseudo option */
|
|
Packit |
8480eb |
for (comma = options; *comma != '\0';) {
|
|
Packit |
8480eb |
const char *cp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (*comma == ',')
|
|
Packit |
8480eb |
comma++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cp = comma;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (*comma != '\0' && *comma != ',')
|
|
Packit |
8480eb |
comma++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (_strncmp("fstype=", cp, 7) == 0) {
|
|
Packit |
8480eb |
int typelen = comma - (cp + 7);
|
|
Packit |
8480eb |
fstype = alloca(typelen + 1);
|
|
Packit |
8480eb |
memcpy(fstype, cp + 7, typelen);
|
|
Packit |
8480eb |
fstype[typelen] = '\0';
|
|
Packit |
8480eb |
} else if (_strncmp("nonstrict", cp, 9) == 0) {
|
|
Packit |
8480eb |
nonstrict = 1;
|
|
Packit |
8480eb |
} else if (_strncmp("strict", cp, 6) == 0 &&
|
|
Packit |
8480eb |
comma - cp == 6) {
|
|
Packit |
8480eb |
nonstrict = 0;
|
|
Packit |
8480eb |
} else if (_strncmp("nobrowse", cp, 8) == 0 ||
|
|
Packit |
8480eb |
_strncmp("browse", cp, 6) == 0 ||
|
|
Packit |
8480eb |
_strncmp("timeout=", cp, 8) == 0) {
|
|
Packit |
8480eb |
if (strcmp(fstype, "autofs") == 0 ||
|
|
Packit |
8480eb |
strstr(cp, "fstype=autofs")) {
|
|
Packit |
8480eb |
memcpy(np, cp, comma - cp + 1);
|
|
Packit |
8480eb |
np += comma - cp + 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else if (_strncmp("no-use-weight-only", cp, 18) == 0) {
|
|
Packit |
8480eb |
use_weight_only = -1;
|
|
Packit |
8480eb |
} else if (_strncmp("use-weight-only", cp, 15) == 0) {
|
|
Packit |
8480eb |
use_weight_only = MOUNT_FLAG_USE_WEIGHT_ONLY;
|
|
Packit |
8480eb |
} else if (_strncmp("bg", cp, 2) == 0 ||
|
|
Packit |
8480eb |
_strncmp("nofg", cp, 4) == 0) {
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
memcpy(np, cp, comma - cp + 1);
|
|
Packit |
8480eb |
np += comma - cp + 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (np > noptions + len) {
|
|
Packit |
8480eb |
warn(ap->logopt, MODPREFIX "options string truncated");
|
|
Packit |
8480eb |
np[len] = '\0';
|
|
Packit |
8480eb |
} else
|
|
Packit |
8480eb |
*(np - 1) = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
options = noptions;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(fstype, "autofs") && ctxt->macros) {
|
|
Packit |
8480eb |
char *noptions = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!options || *options == '\0') {
|
|
Packit |
8480eb |
noptions = alloca(strlen(ctxt->macros) + 1);
|
|
Packit |
8480eb |
*noptions = '\0';
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
int len = strlen(options) + strlen(ctxt->macros) + 2;
|
|
Packit |
8480eb |
noptions = alloca(len);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (noptions) {
|
|
Packit |
8480eb |
strcpy(noptions, options);
|
|
Packit |
8480eb |
strcat(noptions, ",");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (noptions && *noptions != '\0') {
|
|
Packit |
8480eb |
strcat(noptions, ctxt->macros);
|
|
Packit |
8480eb |
options = noptions;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "alloca failed for options");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mountpoint = alloca(namelen + 1);
|
|
Packit |
8480eb |
sprintf(mountpoint, "%.*s", namelen, name);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
type = ap->entry->maps->type;
|
|
Packit |
8480eb |
if (type && !strcmp(type, "hosts")) {
|
|
Packit |
8480eb |
if (options && *options != '\0') {
|
|
Packit |
8480eb |
int len = strlen(options);
|
|
Packit |
8480eb |
int suid = strstr(options, "suid") ? 0 : 7;
|
|
Packit |
8480eb |
int dev = strstr(options, "dev") ? 0 : 6;
|
|
Packit |
8480eb |
int nointr = strstr(options, "nointr") ? 0 : 5;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (suid || dev || nointr) {
|
|
Packit |
8480eb |
char *tmp = alloca(len + suid + dev + nointr + 1);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"alloca failed for options");
|
|
Packit |
8480eb |
if (nonstrict)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(tmp, options);
|
|
Packit |
8480eb |
if (suid)
|
|
Packit |
8480eb |
strcat(tmp, ",nosuid");
|
|
Packit |
8480eb |
if (dev)
|
|
Packit |
8480eb |
strcat(tmp, ",nodev");
|
|
Packit |
8480eb |
if (nointr)
|
|
Packit |
8480eb |
strcat(tmp, ",intr");
|
|
Packit |
8480eb |
options = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
char *tmp = alloca(18);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "alloca failed for options");
|
|
Packit |
8480eb |
if (nonstrict)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
strcpy(tmp, "nosuid,nodev,intr");
|
|
Packit |
8480eb |
options = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
Packit |
8480eb |
if (!strcmp(fstype, "nfs") || !strcmp(fstype, "nfs4")) {
|
|
Packit |
8480eb |
what = alloca(loclen + 1);
|
|
Packit |
8480eb |
memcpy(what, loc, loclen);
|
|
Packit |
8480eb |
what[loclen] = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Add back "[no-]use-weight-only" for NFS mounts only */
|
|
Packit |
8480eb |
if (use_weight_only) {
|
|
Packit |
8480eb |
char *tmp;
|
|
Packit |
8480eb |
int len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (options && *options != '\0') {
|
|
Packit |
8480eb |
len = strlen(options) + 19;
|
|
Packit |
8480eb |
tmp = alloca(len);
|
|
Packit |
8480eb |
strcpy(tmp, options);
|
|
Packit |
8480eb |
strcat(tmp, ",");
|
|
Packit |
8480eb |
if (use_weight_only == MOUNT_FLAG_USE_WEIGHT_ONLY)
|
|
Packit |
8480eb |
strcat(tmp, "use-weight-only");
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
strcat(tmp, "no-use-weight-only");
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
tmp = alloca(19);
|
|
Packit |
8480eb |
if (use_weight_only == MOUNT_FLAG_USE_WEIGHT_ONLY)
|
|
Packit |
8480eb |
strcpy(tmp, "use-weight-only");
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
strcpy(tmp, "no-use-weight-only");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
options = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"mounting root %s, mountpoint %s, "
|
|
Packit |
8480eb |
"what %s, fstype %s, options %s",
|
|
Packit |
8480eb |
root, mountpoint, what, fstype, options);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rv = mount_nfs->mount_mount(ap, root, mountpoint, strlen(mountpoint),
|
|
Packit |
8480eb |
what, fstype, options, mount_nfs->context);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (!loclen)
|
|
Packit |
8480eb |
what = NULL;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
what = alloca(loclen + 1);
|
|
Packit |
8480eb |
if (*loc == ':') {
|
|
Packit |
8480eb |
loclen--;
|
|
Packit |
8480eb |
memcpy(what, loc + 1, loclen);
|
|
Packit |
8480eb |
what[loclen] = '\0';
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
memcpy(what, loc, loclen);
|
|
Packit |
8480eb |
what[loclen] = '\0';
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"mounting root %s, mountpoint %s, "
|
|
Packit |
8480eb |
"what %s, fstype %s, options %s",
|
|
Packit |
8480eb |
root, mountpoint, what, fstype, options);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Generic mount routine */
|
|
Packit |
8480eb |
rv = do_mount(ap, root, mountpoint, strlen(mountpoint), what, fstype,
|
|
Packit |
8480eb |
options);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (nonstrict && rv)
|
|
Packit |
8480eb |
return -rv;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Scan map entry looking for evidence it has multiple key/mapent
|
|
Packit |
8480eb |
* pairs.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static int check_is_multi(const char *mapent)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
const char *p = mapent;
|
|
Packit |
8480eb |
int multi = 0;
|
|
Packit |
8480eb |
int not_first_chunk = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!p) {
|
|
Packit |
8480eb |
logerr(MODPREFIX "unexpected NULL map entry pointer");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*p == '"')
|
|
Packit |
8480eb |
p++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* If first character is "/" it's a multi-mount */
|
|
Packit |
8480eb |
if (*p == '/')
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (*p) {
|
|
Packit |
8480eb |
p = skipspace(p);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* After the first chunk there can be additional
|
|
Packit |
8480eb |
* locations (possibly not multi) or possibly an
|
|
Packit |
8480eb |
* options string if the first entry includes the
|
|
Packit |
8480eb |
* optional '/' (is multi). Following this any
|
|
Packit |
8480eb |
* path that begins with '/' indicates a mutil-mount
|
|
Packit |
8480eb |
* entry.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (not_first_chunk) {
|
|
Packit |
8480eb |
if (*p == '"')
|
|
Packit |
8480eb |
p++;
|
|
Packit |
8480eb |
if (*p == '/' || *p == '-') {
|
|
Packit |
8480eb |
multi = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (*p == '-') {
|
|
Packit |
8480eb |
p += chunklen(p, 0);
|
|
Packit |
8480eb |
p = skipspace(p);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Expect either a path or location
|
|
Packit |
8480eb |
* after which it's a multi mount.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
p += chunklen(p, check_colon(p));
|
|
Packit |
8480eb |
not_first_chunk++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return multi;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int
|
|
Packit |
8480eb |
update_offset_entry(struct autofs_point *ap, const char *name,
|
|
Packit |
8480eb |
const char *m_root, int m_root_len,
|
|
Packit |
8480eb |
const char *path, const char *myoptions, const char *loc,
|
|
Packit |
8480eb |
time_t age)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
char m_key[PATH_MAX + 1];
|
|
Packit |
8480eb |
char m_mapent[MAPENT_MAX_LEN + 1];
|
|
Packit |
8480eb |
int p_len, m_key_len, m_options_len, m_mapent_len;
|
|
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 |
mc = source->mc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Internal hosts map may have loc == NULL */
|
|
Packit |
8480eb |
if (!*path) {
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "syntax error in offset %s -> %s", path, loc);
|
|
Packit |
8480eb |
return CHE_FAIL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p_len = strlen(path);
|
|
Packit |
8480eb |
/* Trailing '/' causes us pain */
|
|
Packit |
8480eb |
if (p_len > 1) {
|
|
Packit |
8480eb |
while (p_len > 1 && path[p_len - 1] == '/')
|
|
Packit |
8480eb |
p_len--;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
m_key_len = m_root_len + p_len;
|
|
Packit |
8480eb |
if (m_key_len > PATH_MAX) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "multi mount key too long");
|
|
Packit |
8480eb |
return CHE_FAIL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
strcpy(m_key, m_root);
|
|
Packit |
8480eb |
strncat(m_key, path, p_len);
|
|
Packit |
8480eb |
m_key[m_key_len] = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
m_options_len = 0;
|
|
Packit |
8480eb |
if (*myoptions)
|
|
Packit |
8480eb |
m_options_len = strlen(myoptions) + 2;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
m_mapent_len = loc ? strlen(loc) : 0;
|
|
Packit |
8480eb |
if (m_mapent_len + m_options_len > MAPENT_MAX_LEN) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "multi mount mapent too long");
|
|
Packit |
8480eb |
return CHE_FAIL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*myoptions) {
|
|
Packit |
8480eb |
strcpy(m_mapent, "-");
|
|
Packit |
8480eb |
strcat(m_mapent, myoptions);
|
|
Packit |
8480eb |
if (loc) {
|
|
Packit |
8480eb |
strcat(m_mapent, " ");
|
|
Packit |
8480eb |
if (loc)
|
|
Packit |
8480eb |
strcat(m_mapent, loc);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (loc)
|
|
Packit |
8480eb |
strcpy(m_mapent, loc);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = cache_update_offset(mc, name, m_key, m_mapent, age);
|
|
Packit |
8480eb |
if (ret == CHE_DUPLICATE) {
|
|
Packit |
8480eb |
warn(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"syntax error or duplicate offset %s -> %s", path, loc);
|
|
Packit |
8480eb |
ret = CHE_OK;
|
|
Packit |
8480eb |
} else if (ret == CHE_FAIL)
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to update multi-mount offset %s -> %s", path, m_mapent);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
ret = CHE_OK;
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"updated multi-mount offset %s -> %s", path, m_mapent);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int validate_location(unsigned int logopt, char *loc)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *ptr = loc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* We don't know much about these */
|
|
Packit |
8480eb |
if (*ptr == ':')
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If a ':/' is present now it must be a host name, except
|
|
Packit |
8480eb |
* for those special file systems like sshfs which use "#"
|
|
Packit |
8480eb |
* and "@" in the host name part and ipv6 addresses that
|
|
Packit |
8480eb |
* have ":", "[" and "]".
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!check_colon(ptr)) {
|
|
Packit |
8480eb |
char *esc;
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Don't forget cases where a colon is present but
|
|
Packit |
8480eb |
* not followed by a "/" or, if there is no colon at
|
|
Packit |
8480eb |
* all, we don't know if it is actually invalid since
|
|
Packit |
8480eb |
* it may be a map name by itself, for example.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!strchr(ptr, ':') ||
|
|
Packit |
8480eb |
((esc = strchr(ptr, '\\')) && *(esc + 1) == ':') ||
|
|
Packit |
8480eb |
!strncmp(ptr, "file:", 5) || !strncmp(ptr, "yp:", 3) ||
|
|
Packit |
8480eb |
!strncmp(ptr, "nis:", 4) || !strncmp(ptr, "nisplus:", 8) ||
|
|
Packit |
8480eb |
!strncmp(ptr, "ldap:", 5) || !strncmp(ptr, "ldaps:", 6) ||
|
|
Packit |
8480eb |
!strncmp(ptr, "sss:", 4) || !strncmp(ptr, "dir:", 4))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
error(logopt,
|
|
Packit |
8480eb |
"expected colon delimeter not found in location %s",
|
|
Packit |
8480eb |
loc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
while (*ptr && strncmp(ptr, ":/", 2)) {
|
|
Packit |
8480eb |
if (!(isalnum(*ptr) ||
|
|
Packit |
8480eb |
*ptr == '-' || *ptr == '.' || *ptr == '_' ||
|
|
Packit |
8480eb |
*ptr == ',' || *ptr == '(' || *ptr == ')' ||
|
|
Packit |
8480eb |
*ptr == '#' || *ptr == '@' || *ptr == ':' ||
|
|
Packit |
8480eb |
*ptr == '[' || *ptr == ']' || *ptr == '%')) {
|
|
Packit |
8480eb |
error(logopt, "invalid character \"%c\" "
|
|
Packit |
8480eb |
"found in location %s", *ptr, loc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
ptr++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*ptr && !strncmp(ptr, ":/", 2))
|
|
Packit |
8480eb |
ptr++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Must always be something following */
|
|
Packit |
8480eb |
if (!*ptr) {
|
|
Packit |
8480eb |
error(logopt, "invalid location %s", loc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int parse_mapent(const char *ent, char *g_options, char **options, char **location, int logopt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
const char *p;
|
|
Packit |
8480eb |
char *myoptions, *loc;
|
|
Packit |
8480eb |
int l;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = ent;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
myoptions = strdup(g_options);
|
|
Packit |
8480eb |
if (!myoptions) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(logopt, MODPREFIX "strdup: %s", estr);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Local options are appended to per-map options */
|
|
Packit |
8480eb |
if (*p == '-') {
|
|
Packit |
8480eb |
do {
|
|
Packit |
8480eb |
char *tmp, *newopt = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = parse_options(p, &newopt, logopt);
|
|
Packit |
8480eb |
if (newopt && strstr(newopt, myoptions)) {
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
myoptions = newopt;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
tmp = concat_options(myoptions, newopt);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
char *estr;
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(logopt, MODPREFIX
|
|
Packit |
8480eb |
"concat_options: %s", estr);
|
|
Packit |
8480eb |
if (newopt)
|
|
Packit |
8480eb |
free(newopt);
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
myoptions = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = skipspace(p);
|
|
Packit |
8480eb |
} while (*p == '-');
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX "gathered options: %s", myoptions);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
l = chunklen(p, check_colon(p));
|
|
Packit |
8480eb |
loc = dequote(p, l, logopt);
|
|
Packit |
8480eb |
if (!loc) {
|
|
Packit |
8480eb |
if (strstr(myoptions, "fstype=autofs") &&
|
|
Packit |
8480eb |
strstr(myoptions, "hosts")) {
|
|
Packit |
8480eb |
warn(logopt, MODPREFIX "possible missing location");
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
*options = myoptions;
|
|
Packit |
8480eb |
*location = NULL;
|
|
Packit |
8480eb |
return (p - ent);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Location can't begin with a '/' */
|
|
Packit |
8480eb |
if (*p == '/') {
|
|
Packit |
8480eb |
warn(logopt, MODPREFIX "error location begins with \"/\"");
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!validate_location(logopt, loc)) {
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX "dequote(\"%.*s\") -> %s", l, p, loc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p += l;
|
|
Packit |
8480eb |
p = skipspace(p);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (*p && ((*p == '"' && *(p + 1) != '/') || (*p != '"' && *p != '/'))) {
|
|
Packit |
8480eb |
char *tmp, *ent_chunk;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
l = chunklen(p, check_colon(p));
|
|
Packit |
8480eb |
ent_chunk = dequote(p, l, logopt);
|
|
Packit |
8480eb |
if (!ent_chunk) {
|
|
Packit |
8480eb |
if (strstr(myoptions, "fstype=autofs") &&
|
|
Packit |
8480eb |
strstr(myoptions, "hosts")) {
|
|
Packit |
8480eb |
warn(logopt, MODPREFIX
|
|
Packit |
8480eb |
"null location or out of memory");
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Location can't begin with a '/' */
|
|
Packit |
8480eb |
if (*p == '/') {
|
|
Packit |
8480eb |
warn(logopt,
|
|
Packit |
8480eb |
MODPREFIX "error location begins with \"/\"");
|
|
Packit |
8480eb |
free(ent_chunk);
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!validate_location(logopt, ent_chunk)) {
|
|
Packit |
8480eb |
free(ent_chunk);
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(logopt, MODPREFIX "dequote(\"%.*s\") -> %s", l, p, ent_chunk);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = realloc(loc, strlen(loc) + l + 2);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX "out of memory");
|
|
Packit |
8480eb |
free(ent_chunk);
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
loc = tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcat(loc, " ");
|
|
Packit |
8480eb |
strcat(loc, ent_chunk);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(ent_chunk);
|
|
Packit |
8480eb |
next:
|
|
Packit |
8480eb |
p += l;
|
|
Packit |
8480eb |
p = skipspace(p);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*options = myoptions;
|
|
Packit |
8480eb |
*location = loc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return (p - ent);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void cleanup_multi_triggers(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct mapent *me, const char *root, int start,
|
|
Packit |
8480eb |
const char *base)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char path[PATH_MAX + 1];
|
|
Packit |
8480eb |
char offset[PATH_MAX + 1];
|
|
Packit |
8480eb |
char *poffset = offset;
|
|
Packit |
8480eb |
struct mapent *oe;
|
|
Packit |
8480eb |
struct list_head *mm_root, *pos;
|
|
Packit |
8480eb |
const char o_root[] = "/";
|
|
Packit |
8480eb |
const char *mm_base;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mm_root = &me->multi->multi_list;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!base)
|
|
Packit |
8480eb |
mm_base = o_root;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
mm_base = base;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pos = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Make sure "none" of the offsets have an active mount. */
|
|
Packit |
8480eb |
while ((poffset = cache_get_offset(mm_base, poffset, start, mm_root, &pos))) {
|
|
Packit |
8480eb |
oe = cache_lookup_offset(mm_base, poffset, start, &me->multi_list);
|
|
Packit |
8480eb |
/* root offset is a special case */
|
|
Packit |
8480eb |
if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(path, root);
|
|
Packit |
8480eb |
strcat(path, poffset);
|
|
Packit |
8480eb |
if (umount(path)) {
|
|
Packit |
8480eb |
error(ap->logopt, "error recovering from mount fail");
|
|
Packit |
8480eb |
error(ap->logopt, "cannot umount offset %s", path);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int mount_subtree(struct autofs_point *ap, struct mapent *me,
|
|
Packit |
8480eb |
const char *name, char *loc, char *options, void *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct mapent *mm;
|
|
Packit |
8480eb |
struct mapent *ro;
|
|
Packit |
8480eb |
char *mm_root, *mm_base, *mm_key;
|
|
Packit |
8480eb |
const char *mnt_root;
|
|
Packit |
8480eb |
unsigned int mm_root_len, mnt_root_len;
|
|
Packit |
8480eb |
int start, ret = 0, rv;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rv = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mm = me->multi;
|
|
Packit |
8480eb |
mm_key = mm->key;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*mm_key == '/') {
|
|
Packit |
8480eb |
mm_root = mm_key;
|
|
Packit |
8480eb |
start = strlen(mm_key);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
start = strlen(ap->path) + strlen(mm_key) + 1;
|
|
Packit |
8480eb |
mm_root = alloca(start + 3);
|
|
Packit |
8480eb |
strcpy(mm_root, ap->path);
|
|
Packit |
8480eb |
strcat(mm_root, "/");
|
|
Packit |
8480eb |
strcat(mm_root, mm_key);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
mm_root_len = strlen(mm_root);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mnt_root = mm_root;
|
|
Packit |
8480eb |
mnt_root_len = mm_root_len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (me == me->multi) {
|
|
Packit |
8480eb |
/* name = NULL */
|
|
Packit |
8480eb |
/* destination = mm_root */
|
|
Packit |
8480eb |
mm_base = "/";
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Mount root offset if it exists */
|
|
Packit |
8480eb |
ro = cache_lookup_offset(mm_base, mm_base, strlen(mm_root), &me->multi_list);
|
|
Packit |
8480eb |
if (ro) {
|
|
Packit |
8480eb |
char *myoptions, *ro_loc, *tmp;
|
|
Packit |
8480eb |
int namelen = name ? strlen(name) : 0;
|
|
Packit |
8480eb |
const char *root;
|
|
Packit |
8480eb |
int ro_len;
|
|
Packit |
8480eb |
|
|
Packit Service |
0f11ce |
myoptions = NULL;
|
|
Packit Service |
0f11ce |
ro_loc = NULL;
|
|
Packit Service |
0f11ce |
|
|
Packit |
8480eb |
rv = parse_mapent(ro->mapent,
|
|
Packit |
8480eb |
options, &myoptions, &ro_loc, ap->logopt);
|
|
Packit |
8480eb |
if (!rv) {
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "failed to parse root offset");
|
|
Packit |
8480eb |
cache_delete_offset_list(me->mc, name);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
ro_len = 0;
|
|
Packit |
8480eb |
if (ro_loc)
|
|
Packit |
8480eb |
ro_len = strlen(ro_loc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = alloca(mnt_root_len + 2);
|
|
Packit |
8480eb |
strcpy(tmp, mnt_root);
|
|
Packit |
8480eb |
tmp[mnt_root_len] = '/';
|
|
Packit |
8480eb |
tmp[mnt_root_len + 1] = '\0';
|
|
Packit |
8480eb |
root = tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rv = sun_mount(ap, root, name, namelen, ro_loc, ro_len, myoptions, ctxt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
if (ro_loc)
|
|
Packit |
8480eb |
free(ro_loc);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ro && rv == 0) {
|
|
Packit |
8480eb |
ret = mount_multi_triggers(ap, me, mnt_root, start, mm_base);
|
|
Packit |
8480eb |
if (ret == -1) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to mount offset triggers");
|
|
Packit |
8480eb |
cleanup_multi_triggers(ap, me, mnt_root, start, mm_base);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else if (rv <= 0) {
|
|
Packit |
8480eb |
ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
|
|
Packit |
8480eb |
if (ret == -1) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to mount offset triggers");
|
|
Packit |
8480eb |
cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
int loclen = strlen(loc);
|
|
Packit |
8480eb |
int namelen = strlen(name);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mnt_root = name;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* name = mm_root + mm_base */
|
|
Packit |
8480eb |
/* destination = mm_root + mm_base = name */
|
|
Packit |
8480eb |
mm_base = &me->key[start];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rv = sun_mount(ap, mnt_root, name, namelen, loc, loclen, options, ctxt);
|
|
Packit |
8480eb |
if (rv == 0) {
|
|
Packit |
8480eb |
ret = mount_multi_triggers(ap, me->multi, mnt_root, start, mm_base);
|
|
Packit |
8480eb |
if (ret == -1) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to mount offset triggers");
|
|
Packit |
8480eb |
cleanup_multi_triggers(ap, me, mnt_root, start, mm_base);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else if (rv < 0) {
|
|
Packit |
8480eb |
char *mm_root_base = alloca(strlen(mm_root) + strlen(mm_base) + 1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(mm_root_base, mm_root);
|
|
Packit |
8480eb |
strcat(mm_root_base, mm_base);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = mount_multi_triggers(ap, me->multi, mm_root_base, start, mm_base);
|
|
Packit |
8480eb |
if (ret == -1) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"failed to mount offset triggers");
|
|
Packit |
8480eb |
cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Mount for base of tree failed */
|
|
Packit |
8480eb |
if (rv > 0)
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Convert fail on nonstrict, non-empty multi-mount
|
|
Packit |
8480eb |
* to success
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (rv < 0 && ret > 0)
|
|
Packit |
8480eb |
rv = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *do_expandsunent(const char *src, const char *key,
|
|
Packit |
8480eb |
const struct substvar *svc, int slashify_colons)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *mapent;
|
|
Packit |
8480eb |
int len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = expandsunent(src, NULL, key, svc, slashify_colons);
|
|
Packit |
8480eb |
if (len == 0) {
|
|
Packit |
8480eb |
errno = EINVAL;
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mapent = malloc(len);
|
|
Packit |
8480eb |
if (!mapent)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
memset(mapent, 0, len);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
expandsunent(src, mapent, key, svc, slashify_colons);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return mapent;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* syntax is:
|
|
Packit |
8480eb |
* [-options] location [location] ...
|
|
Packit |
8480eb |
* [-options] [mountpoint [-options] location [location] ... ]...
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* There are three ways this routine can be called. One where we parse
|
|
Packit |
8480eb |
* offsets in a multi-mount entry adding them to the cache for later lookups.
|
|
Packit |
8480eb |
* Another where we parse a multi-mount entry looking for a root offset mount
|
|
Packit |
8480eb |
* and mount it if it exists and also mount its offsets down to the first
|
|
Packit |
8480eb |
* level nexting point. Finally to mount non multi-mounts and to mount a
|
|
Packit |
8480eb |
* lower level multi-mount nesting point and its offsets.
|
|
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 |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
char *pmapent, *options;
|
|
Packit |
8480eb |
const char *p;
|
|
Packit |
8480eb |
int mapent_len, rv = 0;
|
|
Packit |
8480eb |
int cur_state;
|
|
Packit |
8480eb |
int slashify = ctxt->slashify_colons;
|
|
Packit |
8480eb |
unsigned int append_options;
|
|
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 |
mc = source->mc;
|
|
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 |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Offset map entries have been expanded already, avoid expanding
|
|
Packit |
8480eb |
* them again so that the quote handling is consistent between map
|
|
Packit |
8480eb |
* entry locations and (previously expanded) offset map entry
|
|
Packit |
8480eb |
* locations.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (*name == '/') {
|
|
Packit |
8480eb |
cache_readlock(mc);
|
|
Packit |
8480eb |
me = cache_lookup_distinct(mc, name);
|
|
Packit |
8480eb |
if (me && me->multi && me->multi != me) {
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
mapent_len = strlen(mapent) + 1;
|
|
Packit |
8480eb |
pmapent = malloc(mapent_len + 1);
|
|
Packit |
8480eb |
if (!pmapent) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
memset(pmapent, 0, mapent_len + 1);
|
|
Packit |
8480eb |
strcpy(pmapent, mapent);
|
|
Packit |
8480eb |
goto dont_expand;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
macro_lock();
|
|
Packit |
8480eb |
ctxt->subst = addstdenv(ctxt->subst, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pmapent = do_expandsunent(mapent, name, ctxt->subst, slashify);
|
|
Packit |
8480eb |
if (!pmapent) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "failed to expand map entry");
|
|
Packit |
8480eb |
ctxt->subst = removestdenv(ctxt->subst, NULL);
|
|
Packit |
8480eb |
macro_unlock();
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
mapent_len = strlen(pmapent) + 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ctxt->subst = removestdenv(ctxt->subst, NULL);
|
|
Packit |
8480eb |
macro_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
dont_expand:
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX "expanded entry: %s", pmapent);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
append_options = defaults_get_append_options();
|
|
Packit |
8480eb |
options = strdup(ctxt->optstr ? ctxt->optstr : "");
|
|
Packit |
8480eb |
if (!options) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
logerr(MODPREFIX "strdup: %s", estr);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = skipspace(pmapent);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Deal with 0 or more options */
|
|
Packit |
8480eb |
if (*p == '-') {
|
|
Packit |
8480eb |
char *tmp, *mnt_options = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
do {
|
|
Packit |
8480eb |
char *noptions = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = parse_options(p, &noptions, ap->logopt);
|
|
Packit |
8480eb |
if (mnt_options && noptions && strstr(noptions, mnt_options)) {
|
|
Packit |
8480eb |
free(mnt_options);
|
|
Packit |
8480eb |
mnt_options = noptions;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
tmp = concat_options(mnt_options, noptions);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "concat_options: %s", estr);
|
|
Packit |
8480eb |
if (noptions)
|
|
Packit |
8480eb |
free(noptions);
|
|
Packit |
8480eb |
if (mnt_options)
|
|
Packit |
8480eb |
free(mnt_options);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
mnt_options = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = skipspace(p);
|
|
Packit |
8480eb |
} while (*p == '-');
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (options && !append_options) {
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
options = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (append_options) {
|
|
Packit |
8480eb |
if (options && mnt_options && strstr(mnt_options, options)) {
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
options = mnt_options;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
tmp = concat_options(options, mnt_options);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "concat_options: %s", estr);
|
|
Packit |
8480eb |
if (options)
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
if (mnt_options)
|
|
Packit |
8480eb |
free(mnt_options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
options = tmp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else
|
|
Packit |
8480eb |
options = mnt_options;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX "gathered options: %s", options);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (check_is_multi(p)) {
|
|
Packit |
8480eb |
char *m_root = NULL;
|
|
Packit |
8480eb |
int m_root_len;
|
|
Packit |
8480eb |
time_t age;
|
|
Packit |
8480eb |
int l;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* If name starts with "/" it's a direct mount */
|
|
Packit |
8480eb |
if (*name == '/') {
|
|
Packit |
8480eb |
m_root_len = name_len;
|
|
Packit |
8480eb |
m_root = alloca(m_root_len + 1);
|
|
Packit |
8480eb |
if (!m_root) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
logerr(MODPREFIX "alloca: %s", estr);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
strcpy(m_root, name);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
m_root_len = strlen(ap->path) + name_len + 1;
|
|
Packit |
8480eb |
m_root = alloca(m_root_len + 1);
|
|
Packit |
8480eb |
if (!m_root) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
logerr(MODPREFIX "alloca: %s", estr);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
strcpy(m_root, ap->path);
|
|
Packit |
8480eb |
strcat(m_root, "/");
|
|
Packit |
8480eb |
strcat(m_root, name);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
Packit |
8480eb |
cache_readlock(mc);
|
|
Packit |
8480eb |
me = cache_lookup_distinct(mc, name);
|
|
Packit |
8480eb |
if (!me) {
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "can't find multi root %s", name);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_multi_writelock(me);
|
|
Packit |
8480eb |
/* So we know we're the multi-mount root */
|
|
Packit |
8480eb |
if (!me->multi)
|
|
Packit |
8480eb |
me->multi = me;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* The amd host mount type assumes the lookup name
|
|
Packit |
8480eb |
* is the host name for the host mount but amd uses
|
|
Packit |
8480eb |
* ${rhost} for this.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* This introduces the possibility of multiple
|
|
Packit |
8480eb |
* concurrent mount requests since constructing a
|
|
Packit |
8480eb |
* mount tree that isn't under the lookup name can't
|
|
Packit |
8480eb |
* take advantage of the kernel queuing of other
|
|
Packit |
8480eb |
* concurrent lookups while the mount tree is
|
|
Packit |
8480eb |
* constructed.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Consequently multi-mount updates (currently only
|
|
Packit |
8480eb |
* done for the internal hosts map which the amd
|
|
Packit |
8480eb |
* parser also uses for its hosts map) can't be
|
|
Packit |
8480eb |
* allowed for amd mounts.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (source->flags & MAP_FLAG_FORMAT_AMD) {
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
cache_multi_unlock(me);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
age = me->age;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* It's a multi-mount; deal with it */
|
|
Packit |
8480eb |
do {
|
|
Packit |
8480eb |
char *path, *myoptions, *loc;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((*p == '"' && *(p + 1) != '/') || (*p != '"' && *p != '/')) {
|
|
Packit |
8480eb |
l = 0;
|
|
Packit |
8480eb |
path = dequote("/", 1, ap->logopt);
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "dequote(\"/\") -> %s", path);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
l = span_space(p, mapent_len - (p - pmapent));
|
|
Packit |
8480eb |
path = sanitize_path(p, l, LKP_MULTI, ap->logopt);
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"dequote(\"%.*s\") -> %s", l, p, path);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!path) {
|
|
Packit |
8480eb |
warn(ap->logopt, MODPREFIX "null path or out of memory");
|
|
Packit |
8480eb |
cache_delete_offset_list(mc, name);
|
|
Packit |
8480eb |
cache_multi_unlock(me);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p += l;
|
|
Packit |
8480eb |
p = skipspace(p);
|
|
Packit |
8480eb |
|
|
Packit Service |
0f11ce |
myoptions = NULL;
|
|
Packit Service |
0f11ce |
loc = NULL;
|
|
Packit Service |
0f11ce |
|
|
Packit |
8480eb |
l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
|
|
Packit |
8480eb |
if (!l) {
|
|
Packit |
8480eb |
cache_delete_offset_list(mc, name);
|
|
Packit |
8480eb |
cache_multi_unlock(me);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
free(path);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p += l;
|
|
Packit |
8480eb |
p = skipspace(p);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_current_wait(ap->entry);
|
|
Packit |
8480eb |
ap->entry->current = source;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = update_offset_entry(ap, name,
|
|
Packit |
8480eb |
m_root, m_root_len,
|
|
Packit |
8480eb |
path, myoptions, loc, age);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (status != CHE_OK) {
|
|
Packit |
8480eb |
warn(ap->logopt, MODPREFIX "error adding multi-mount");
|
|
Packit |
8480eb |
cache_delete_offset_list(mc, name);
|
|
Packit |
8480eb |
cache_multi_unlock(me);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
free(path);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
if (loc)
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (loc)
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
free(path);
|
|
Packit |
8480eb |
free(myoptions);
|
|
Packit |
8480eb |
} while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* We've got the ordered list of multi-mount entries so go
|
|
Packit |
8480eb |
* through and remove any stale entries if this is the top
|
|
Packit |
8480eb |
* of the multi-mount and set the parent entry of each.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (me == me->multi)
|
|
Packit |
8480eb |
clean_stale_multi_triggers(ap, me, NULL, NULL);
|
|
Packit |
8480eb |
cache_set_parents(me);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rv = mount_subtree(ap, me, name, NULL, options, ctxt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_multi_unlock(me);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
/* Normal (and non-root multi-mount) entries */
|
|
Packit |
8480eb |
char *loc;
|
|
Packit |
8480eb |
int loclen;
|
|
Packit |
8480eb |
int l;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If this is an offset belonging to a multi-mount entry
|
|
Packit |
8480eb |
* it's already been parsed (above) and any option string
|
|
Packit |
8480eb |
* has already been stripped so just use the remainder.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
cache_readlock(mc);
|
|
Packit |
8480eb |
if (*name == '/' &&
|
|
Packit |
8480eb |
(me = cache_lookup_distinct(mc, name)) && me->multi) {
|
|
Packit |
8480eb |
loc = strdup(p);
|
|
Packit |
8480eb |
if (!loc) {
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
warn(ap->logopt, MODPREFIX "out of memory");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_multi_writelock(me);
|
|
Packit |
8480eb |
rv = mount_subtree(ap, me, name, loc, options, ctxt);
|
|
Packit |
8480eb |
cache_multi_unlock(me);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
l = chunklen(p, check_colon(p));
|
|
Packit |
8480eb |
loc = dequote(p, l, ap->logopt);
|
|
Packit |
8480eb |
if (!loc) {
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
warn(ap->logopt, MODPREFIX "null location or out of memory");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Location can't begin with a '/' */
|
|
Packit |
8480eb |
if (*p == '/') {
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "error location begins with \"/\"");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!validate_location(ap->logopt, loc)) {
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "dequote(\"%.*s\") -> %s", l, p, loc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p += l;
|
|
Packit |
8480eb |
p = skipspace(p);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (*p) {
|
|
Packit |
8480eb |
char *tmp, *ent;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
l = chunklen(p, check_colon(p));
|
|
Packit |
8480eb |
ent = dequote(p, l, ap->logopt);
|
|
Packit |
8480eb |
if (!ent) {
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "null location or out of memory");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!validate_location(ap->logopt, ent)) {
|
|
Packit |
8480eb |
free(ent);
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "dequote(\"%.*s\") -> %s", l, p, ent);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = realloc(loc, strlen(loc) + l + 2);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
free(ent);
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "out of memory");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
loc = tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcat(loc, " ");
|
|
Packit |
8480eb |
strcat(loc, ent);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(ent);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p += l;
|
|
Packit |
8480eb |
p = skipspace(p);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If options are asking for a hosts map loc should be
|
|
Packit |
8480eb |
* NULL but we see it can contain junk, so ....
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if ((strstr(options, "fstype=autofs") &&
|
|
Packit |
8480eb |
strstr(options, "hosts"))) {
|
|
Packit |
8480eb |
if (loc) {
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
loc = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
loclen = 0;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
loclen = strlen(loc);
|
|
Packit |
8480eb |
if (loclen == 0) {
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "entry %s is empty!", name);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "core of entry: options=%s, loc=%.*s",
|
|
Packit |
8480eb |
options, loclen, loc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(ap->path, "/-"))
|
|
Packit |
8480eb |
rv = sun_mount(ap, name, name, name_len,
|
|
Packit |
8480eb |
loc, loclen, options, ctxt);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
rv = sun_mount(ap, ap->path, name, name_len,
|
|
Packit |
8480eb |
loc, loclen, options, ctxt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (loc)
|
|
Packit |
8480eb |
free(loc);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
free(pmapent);
|
|
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 |
}
|