autofs/SOURCES/autofs-5.1.6-move-lib_master_c-to-daemon_master_c.patch
2021-10-08 09:51:03 +00:00

6878 lines
145 KiB
Diff

autofs-5.1.6 - move lib/master.c to daemon/master.c
From: Ian Kent <raven@themaw.net>
The lib subdirectory isn't really the right place for master.c, move
it to the deamon subdirectory.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1
daemon/Makefile | 19
daemon/master.c | 1885 ++++++++++++++++++++++++++++++++++++++++++++++++++
daemon/master_parse.y | 983 ++++++++++++++++++++++++++
daemon/master_tok.l | 504 +++++++++++++
lib/Makefile | 23
lib/master.c | 1885 --------------------------------------------------
lib/master_parse.y | 983 --------------------------
lib/master_tok.l | 504 -------------
9 files changed, 3394 insertions(+), 3393 deletions(-)
create mode 100644 daemon/master.c
create mode 100644 daemon/master_parse.y
create mode 100644 daemon/master_tok.l
delete mode 100644 lib/master.c
delete mode 100644 lib/master_parse.y
delete mode 100644 lib/master_tok.l
--- autofs-5.1.4.orig/CHANGELOG
+++ autofs-5.1.4/CHANGELOG
@@ -133,6 +133,7 @@ xx/xx/2018 autofs-5.1.5
- remove unused function tree_get_mnt_list().
- only add expre alarm for active mounts.
- move submount check into conditional_alarm_add().
+- move lib/master.c to daemon/master.c.
19/12/2017 autofs-5.1.4
- fix spec file url.
--- autofs-5.1.4.orig/daemon/Makefile
+++ autofs-5.1.4/daemon/Makefile
@@ -6,9 +6,12 @@
include ../Makefile.rules
SRCS = automount.c indirect.c direct.c spawn.c module.c mount.c \
- lookup.c state.c flag.c
+ master.c master_tok.l master_parse.y lookup.c state.c flag.c
OBJS = automount.o indirect.o direct.o spawn.o module.o mount.o \
- lookup.o state.o flag.o
+ master.o master_tok.o master_parse.tab.o lookup.o state.o \
+ flag.o
+
+YACCSRC = master_tok.c master_parse.tab.c master_parse.tab.h
version := $(shell cat ../.version)
@@ -38,8 +41,18 @@ automount: $(OBJS) $(AUTOFS_LIB)
$(CC) $(DAEMON_LDFLAGS) -o automount $(OBJS) $(LDFLAGS) $(AUTOFS_LIB) $(LIBS)
$(STRIP) automount
+master_tok.c: master_tok.l
+ $(LEX) -o$@ -Pmaster_ $?
+
+master_parse.tab.c master_parse.tab.h: master_parse.y
+ $(YACC) -v -d -p master_ -b master_parse $?
+
+master_tok.o: master_tok.c master_parse.tab.h
+
+master_parse.tab.o: master_parse.tab.c master_parse.tab.h
+
clean:
- rm -f *.o *.s *~ automount
+ rm -f *.o *.s *~ $(YACCSRC) *.output *~ automount
install: all
install -d -m 755 $(INSTALLROOT)$(sbindir)
--- /dev/null
+++ autofs-5.1.4/daemon/master.c
@@ -0,0 +1,1885 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * master.c - master map utility routines.
+ *
+ * Copyright 2006 Ian Kent <raven@themaw.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <limits.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include "automount.h"
+
+/* The root of the map entry tree */
+struct master *master_list = NULL;
+
+extern const char *global_options;
+extern long global_negative_timeout;
+
+/* Attribute to create a joinable thread */
+extern pthread_attr_t th_attr;
+
+extern struct startup_cond suc;
+
+static struct map_source *
+__master_find_map_source(struct master_mapent *,
+ const char *, const char *, int, const char **);
+
+static pthread_mutex_t master_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void master_mutex_lock(void)
+{
+ int status = pthread_mutex_lock(&master_mutex);
+ if (status)
+ fatal(status);
+}
+
+void master_mutex_unlock(void)
+{
+ int status = pthread_mutex_unlock(&master_mutex);
+ if (status)
+ fatal(status);
+}
+
+void master_mutex_lock_cleanup(void *arg)
+{
+ master_mutex_unlock();
+ return;
+}
+
+int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
+ unsigned nobind, unsigned ghost, int submount)
+{
+ struct autofs_point *ap;
+ int status;
+
+ ap = malloc(sizeof(struct autofs_point));
+ if (!ap)
+ return 0;
+
+ ap->state = ST_INIT;
+
+ ap->state_pipe[0] = -1;
+ ap->state_pipe[1] = -1;
+ ap->logpri_fifo = -1;
+
+ ap->path = strdup(entry->path);
+ if (!ap->path) {
+ free(ap);
+ return 0;
+ }
+ ap->pref = NULL;
+
+ ap->entry = entry;
+ ap->exp_thread = 0;
+ ap->readmap_thread = 0;
+ /*
+ * Program command line option overrides config.
+ * We can't use 0 negative timeout so use default.
+ */
+ if (global_negative_timeout <= 0)
+ ap->negative_timeout = defaults_get_negative_timeout();
+ else
+ ap->negative_timeout = global_negative_timeout;
+ ap->exp_timeout = defaults_get_timeout();
+ ap->exp_runfreq = 0;
+ ap->flags = 0;
+
+ if (defaults_get_use_ignore_mount_option())
+ ap->flags = MOUNT_FLAG_IGNORE;
+ if (ghost)
+ ap->flags |= MOUNT_FLAG_GHOST;
+
+ if (nobind)
+ ap->flags |= MOUNT_FLAG_NOBIND;
+
+ if (ap->path[1] == '-')
+ ap->type = LKP_DIRECT;
+ else
+ ap->type = LKP_INDIRECT;
+
+ ap->logopt = logopt;
+
+ ap->parent = NULL;
+ ap->thid = 0;
+ ap->submnt_count = 0;
+ ap->submount = submount;
+ INIT_LIST_HEAD(&ap->mounts);
+ INIT_LIST_HEAD(&ap->submounts);
+ INIT_LIST_HEAD(&ap->amdmounts);
+ ap->shutdown = 0;
+
+ status = pthread_mutex_init(&ap->mounts_mutex, NULL);
+ if (status) {
+ free(ap->path);
+ free(ap);
+ return 0;
+ }
+ ap->mode = 0;
+
+ entry->ap = ap;
+
+ return 1;
+}
+
+void master_free_autofs_point(struct autofs_point *ap)
+{
+ struct list_head *p, *head;
+ int status;
+
+ if (!ap)
+ return;
+
+ mounts_mutex_lock(ap);
+ head = &ap->amdmounts;
+ p = head->next;
+ while (p != head) {
+ struct mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
+ p = p->next;
+ ext_mount_remove(mnt->ext_mp);
+ mnts_remove_amdmount(mnt->mp);
+ }
+ mounts_mutex_unlock(ap);
+
+ status = pthread_mutex_destroy(&ap->mounts_mutex);
+ if (status)
+ fatal(status);
+
+ if (ap->pref)
+ free(ap->pref);
+ free(ap->path);
+ free(ap);
+}
+
+struct map_source *
+master_add_map_source(struct master_mapent *entry,
+ char *type, char *format, time_t age,
+ int argc, const char **argv)
+{
+ struct map_source *source;
+ char *ntype, *nformat;
+ const char **tmpargv;
+
+ source = malloc(sizeof(struct map_source));
+ if (!source)
+ return NULL;
+ memset(source, 0, sizeof(struct map_source));
+ source->ref = 1;
+
+ if (type) {
+ ntype = strdup(type);
+ if (!ntype) {
+ master_free_map_source(source, 0);
+ return NULL;
+ }
+ source->type = ntype;
+ }
+
+ if (format) {
+ nformat = strdup(format);
+ if (!nformat) {
+ master_free_map_source(source, 0);
+ return NULL;
+ }
+ source->format = nformat;
+ if (!strcmp(nformat, "amd"))
+ source->flags |= MAP_FLAG_FORMAT_AMD;
+ }
+
+ source->age = age;
+ source->stale = 1;
+
+ tmpargv = copy_argv(argc, argv);
+ if (!tmpargv) {
+ master_free_map_source(source, 0);
+ return NULL;
+ }
+ source->argc = argc;
+ source->argv = tmpargv;
+ if (source->argv[0])
+ source->name = strdup(source->argv[0]);
+
+ master_source_writelock(entry);
+
+ if (!entry->maps) {
+ source->mc = cache_init(entry->ap, source);
+ if (!source->mc) {
+ master_free_map_source(source, 0);
+ master_source_unlock(entry);
+ return NULL;
+ }
+ entry->maps = source;
+ } else {
+ struct map_source *this, *last, *next;
+
+ /* Typically there only a few map sources */
+
+ this = __master_find_map_source(entry, type, format, argc, tmpargv);
+ if (this) {
+ debug(entry->ap->logopt,
+ "map source used without taking reference");
+ this->age = age;
+ master_free_map_source(source, 0);
+ master_source_unlock(entry);
+ return this;
+ }
+
+ source->mc = cache_init(entry->ap, source);
+ if (!source->mc) {
+ master_free_map_source(source, 0);
+ master_source_unlock(entry);
+ return NULL;
+ }
+
+ last = NULL;
+ next = entry->maps;
+ while (next) {
+ last = next;
+ next = next->next;
+ }
+ if (last)
+ last->next = source;
+ else
+ entry->maps = source;
+ }
+
+ master_source_unlock(entry);
+
+ return source;
+}
+
+static int compare_source_type_and_format(struct map_source *map, const char *type, const char *format)
+{
+ int res = 0;
+
+ if (type) {
+ if (!map->type)
+ goto done;
+
+ if (strcmp(map->type, type))
+ goto done;
+ } else if (map->type)
+ goto done;
+
+ if (format) {
+ if (!map->format)
+ goto done;
+
+ if (strcmp(map->format, format))
+ goto done;
+ } else if (map->format)
+ goto done;
+
+ res = 1;
+done:
+ return res;
+}
+
+static struct map_source *
+__master_find_map_source(struct master_mapent *entry,
+ const char *type, const char *format,
+ int argc, const char **argv)
+{
+ struct map_source *map;
+ struct map_source *source = NULL;
+ int res;
+
+ map = entry->maps;
+ while (map) {
+ res = compare_source_type_and_format(map, type, format);
+ if (!res)
+ goto next;
+
+ res = compare_argv(map->argc, map->argv, argc, argv);
+ if (!res)
+ goto next;
+
+ source = map;
+ break;
+next:
+ map = map->next;
+ }
+
+ return source;
+}
+
+struct map_source *master_find_map_source(struct master_mapent *entry,
+ const char *type, const char *format,
+ int argc, const char **argv)
+{
+ struct map_source *source = NULL;
+
+ master_source_readlock(entry);
+ source = __master_find_map_source(entry, type, format, argc, argv);
+ master_source_unlock(entry);
+
+ return source;
+}
+
+struct map_source *
+master_get_map_source(struct master_mapent *entry,
+ const char *type, const char *format,
+ int argc, const char **argv)
+{
+ struct map_source *source = NULL;
+
+ master_source_readlock(entry);
+ source = __master_find_map_source(entry, type, format, argc, argv);
+ if (source)
+ source->ref++;
+ master_source_unlock(entry);
+
+ return source;
+}
+
+static void __master_free_map_source(struct map_source *source, unsigned int free_cache)
+{
+ /* instance map sources are not ref counted */
+ if (source->ref && --source->ref)
+ return;
+ if (source->type)
+ free(source->type);
+ if (source->format)
+ free(source->format);
+ if (source->name)
+ free(source->name);
+ if (free_cache && source->mc)
+ cache_release(source);
+ if (source->lookup) {
+ struct map_source *instance;
+
+ instance = source->instance;
+ while (instance) {
+ if (instance->lookup)
+ close_lookup(instance->lookup);
+ instance = instance->next;
+ }
+ close_lookup(source->lookup);
+ }
+ if (source->argv)
+ free_argv(source->argc, source->argv);
+ if (source->instance) {
+ struct map_source *instance, *next;
+
+ instance = source->instance;
+ while (instance) {
+ next = instance->next;
+ __master_free_map_source(instance, 0);
+ instance = next;
+ }
+ }
+
+ free(source);
+
+ return;
+}
+
+void master_free_map_source(struct map_source *source, unsigned int free_cache)
+{
+ int status;
+
+ status = pthread_mutex_lock(&instance_mutex);
+ if (status)
+ fatal(status);
+
+ __master_free_map_source(source, free_cache);
+
+ status = pthread_mutex_unlock(&instance_mutex);
+ if (status)
+ fatal(status);
+}
+
+struct map_source *master_find_source_instance(struct map_source *source, const char *type, const char *format, int argc, const char **argv)
+{
+ struct map_source *map;
+ struct map_source *instance = NULL;
+ int status, res;
+
+ status = pthread_mutex_lock(&instance_mutex);
+ if (status)
+ fatal(status);
+
+ map = source->instance;
+ while (map) {
+ res = compare_source_type_and_format(map, type, format);
+ if (!res)
+ goto next;
+
+ if (!argv) {
+ instance = map;
+ break;
+ }
+
+ res = compare_argv(map->argc, map->argv, argc, argv);
+ if (!res)
+ goto next;
+
+ instance = map;
+ break;
+next:
+ map = map->next;
+ }
+
+ status = pthread_mutex_unlock(&instance_mutex);
+ if (status)
+ fatal(status);
+
+ return instance;
+}
+
+struct map_source *
+master_add_source_instance(struct map_source *source, const char *type, const char *format, time_t age, int argc, const char **argv)
+{
+ struct map_source *instance;
+ struct map_source *new;
+ char *ntype, *nformat;
+ const char **tmpargv;
+ int status;
+
+ instance = master_find_source_instance(source, type, format, argc, argv);
+ if (instance)
+ return instance;
+
+ new = malloc(sizeof(struct map_source));
+ if (!new)
+ return NULL;
+ memset(new, 0, sizeof(struct map_source));
+
+ if (type) {
+ ntype = strdup(type);
+ if (!ntype) {
+ master_free_map_source(new, 0);
+ return NULL;
+ }
+ new->type = ntype;
+ }
+
+ if (format) {
+ nformat = strdup(format);
+ if (!nformat) {
+ master_free_map_source(new, 0);
+ return NULL;
+ }
+ new->format = nformat;
+ if (!strcmp(nformat, "amd"))
+ new->flags |= MAP_FLAG_FORMAT_AMD;
+ }
+
+ new->age = age;
+ new->master_line = 0;
+ new->mc = source->mc;
+ new->exp_timeout = source->exp_timeout;
+ new->stale = 1;
+
+ tmpargv = copy_argv(argc, argv);
+ if (!tmpargv) {
+ master_free_map_source(new, 0);
+ return NULL;
+ }
+ new->argc = argc;
+ new->argv = tmpargv;
+ if (source->name)
+ new->name = strdup(source->name);
+
+ status = pthread_mutex_lock(&instance_mutex);
+ if (status)
+ fatal(status);
+
+ if (!source->instance)
+ source->instance = new;
+ else {
+ /*
+ * We know there's no other instance of this
+ * type so just add to head of list
+ */
+ new->next = source->instance;
+ source->instance = new;
+ }
+
+ status = pthread_mutex_unlock(&instance_mutex);
+ if (status)
+ fatal(status);
+
+ return new;
+}
+
+int check_stale_instances(struct map_source *source)
+{
+ struct map_source *map;
+
+ if (!source)
+ return 0;
+
+ map = source->instance;
+ while (map) {
+ if (map->stale)
+ return 1;
+ if (check_stale_instances(map))
+ return 1;
+ map = map->next;
+ }
+
+ return 0;
+}
+
+void clear_stale_instances(struct map_source *source)
+{
+ struct map_source *map;
+
+ if (!source)
+ return;
+
+ map = source->instance;
+ while (map) {
+ clear_stale_instances(map);
+ if (map->stale)
+ map->stale = 0;
+ map = map->next;
+ }
+
+ return;
+}
+
+void send_map_update_request(struct autofs_point *ap)
+{
+ struct map_source *map;
+ int status, need_update = 0;
+
+ status = pthread_mutex_lock(&instance_mutex);
+ if (status)
+ fatal(status);
+
+ map = ap->entry->maps;
+ while (map) {
+ if (check_stale_instances(map))
+ map->stale = 1;
+ if (map->stale) {
+ need_update = 1;
+ break;
+ }
+ map = map->next;
+ }
+
+ status = pthread_mutex_unlock(&instance_mutex);
+ if (status)
+ fatal(status);
+
+ if (!need_update)
+ return;
+
+ st_add_task(ap, ST_READMAP);
+
+ return;
+}
+
+void master_source_writelock(struct master_mapent *entry)
+{
+ int status;
+
+ status = pthread_rwlock_wrlock(&entry->source_lock);
+ if (status) {
+ logmsg("master_mapent source write lock failed");
+ fatal(status);
+ }
+ return;
+}
+
+void master_source_readlock(struct master_mapent *entry)
+{
+ int retries = 25;
+ int status;
+
+ while (retries--) {
+ status = pthread_rwlock_rdlock(&entry->source_lock);
+ if (status != EAGAIN && status != EBUSY)
+ break;
+ else {
+ struct timespec t = { 0, 200000000 };
+ struct timespec r;
+
+ if (status == EAGAIN)
+ logmsg("master_mapent source too many readers");
+ else
+ logmsg("master_mapent source write lock held");
+
+ while (nanosleep(&t, &r) == -1 && errno == EINTR)
+ memcpy(&t, &r, sizeof(struct timespec));
+ }
+ }
+
+ if (status) {
+ logmsg("master_mapent source read lock failed");
+ fatal(status);
+ }
+
+ return;
+}
+
+void master_source_unlock(struct master_mapent *entry)
+{
+ int status;
+
+ status = pthread_rwlock_unlock(&entry->source_lock);
+ if (status) {
+ logmsg("master_mapent source unlock failed");
+ fatal(status);
+ }
+ return;
+}
+
+void master_source_lock_cleanup(void *arg)
+{
+ struct master_mapent *entry = (struct master_mapent *) arg;
+
+ master_source_unlock(entry);
+
+ return;
+}
+
+void master_source_current_wait(struct master_mapent *entry)
+{
+ int status;
+
+ status = pthread_mutex_lock(&entry->current_mutex);
+ if (status) {
+ logmsg("entry current source lock failed");
+ fatal(status);
+ }
+
+ while (entry->current != NULL) {
+ status = pthread_cond_wait(
+ &entry->current_cond, &entry->current_mutex);
+ if (status) {
+ logmsg("entry current source condition wait failed");
+ fatal(status);
+ }
+ }
+
+ return;
+}
+
+void master_source_current_signal(struct master_mapent *entry)
+{
+ int status;
+
+ status = pthread_cond_signal(&entry->current_cond);
+ if (status) {
+ logmsg("entry current source condition signal failed");
+ fatal(status);
+ }
+
+ status = pthread_mutex_unlock(&entry->current_mutex);
+ if (status) {
+ logmsg("entry current source unlock failed");
+ fatal(status);
+ }
+
+ return;
+}
+
+struct master_mapent *master_find_mapent(struct master *master, const char *path)
+{
+ struct list_head *head, *p;
+
+ head = &master->mounts;
+ list_for_each(p, head) {
+ struct master_mapent *entry;
+
+ entry = list_entry(p, struct master_mapent, list);
+
+ if (!strcmp(entry->path, path))
+ return entry;
+ }
+
+ return NULL;
+}
+
+unsigned int master_partial_match_mapent(struct master *master, const char *path)
+{
+ struct list_head *head, *p;
+ size_t path_len = strlen(path);
+ int ret = 0;
+
+ head = &master->mounts;
+ list_for_each(p, head) {
+ struct master_mapent *entry;
+ size_t entry_len;
+ size_t cmp_len;
+
+ entry = list_entry(p, struct master_mapent, list);
+
+ entry_len = strlen(entry->path);
+ cmp_len = min(entry_len, path_len);
+
+ if (!strncmp(entry->path, path, cmp_len)) {
+ /* paths are equal, matching master map entry ? */
+ if (entry_len == path_len) {
+ if (entry->maps &&
+ entry->maps->flags & MAP_FLAG_FORMAT_AMD)
+ ret = 1;
+ else
+ ret = -1;
+ break;
+ }
+
+ /* amd mount conflicts with entry mount */
+ if (entry_len > path_len &&
+ *(entry->path + path_len) == '/') {
+ ret = -1;
+ break;
+ }
+
+ /* entry mount conflicts with amd mount */
+ if (entry_len < path_len &&
+ *(path + entry_len) == '/') {
+ ret = -1;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
+{
+ struct master_mapent *entry;
+ int status;
+ char *tmp;
+
+ entry = malloc(sizeof(struct master_mapent));
+ if (!entry)
+ return NULL;
+
+ memset(entry, 0, sizeof(struct master_mapent));
+
+ tmp = strdup(path);
+ if (!tmp) {
+ free(entry);
+ return NULL;
+ }
+ entry->path = tmp;
+
+ entry->thid = 0;
+ entry->age = age;
+ entry->master = master;
+ entry->current = NULL;
+ entry->maps = NULL;
+ entry->ap = NULL;
+
+ status = pthread_rwlock_init(&entry->source_lock, NULL);
+ if (status)
+ fatal(status);
+
+ status = pthread_mutex_init(&entry->current_mutex, NULL);
+ if (status)
+ fatal(status);
+
+ status = pthread_cond_init(&entry->current_cond, NULL);
+ if (status)
+ fatal(status);
+
+ INIT_LIST_HEAD(&entry->list);
+
+ return entry;
+}
+
+void master_add_mapent(struct master *master, struct master_mapent *entry)
+{
+ list_add_tail(&entry->list, &master->mounts);
+ return;
+}
+
+void master_remove_mapent(struct master_mapent *entry)
+{
+ struct master *master = entry->master;
+
+ if (entry->ap->submount)
+ return;
+
+ if (!list_empty(&entry->list)) {
+ list_del_init(&entry->list);
+ list_add(&entry->join, &master->completed);
+ }
+
+ return;
+}
+
+void master_free_mapent_sources(struct master_mapent *entry, unsigned int free_cache)
+{
+ if (entry->maps) {
+ struct map_source *m, *n;
+
+ m = entry->maps;
+ while (m) {
+ n = m->next;
+ master_free_map_source(m, free_cache);
+ m = n;
+ }
+ entry->maps = NULL;
+ }
+
+ return;
+}
+
+void master_free_mapent(struct master_mapent *entry)
+{
+ int status;
+
+ if (entry->path)
+ free(entry->path);
+
+ master_free_autofs_point(entry->ap);
+
+ status = pthread_rwlock_destroy(&entry->source_lock);
+ if (status)
+ fatal(status);
+
+ status = pthread_mutex_destroy(&entry->current_mutex);
+ if (status)
+ fatal(status);
+
+ status = pthread_cond_destroy(&entry->current_cond);
+ if (status)
+ fatal(status);
+
+ free(entry);
+
+ return;
+}
+
+struct master *master_new(const char *name, unsigned int timeout, unsigned int flags)
+{
+ struct master *master;
+ char *tmp;
+
+ master = malloc(sizeof(struct master));
+ if (!master)
+ return NULL;
+
+ if (!name)
+ tmp = (char *) defaults_get_master_map();
+ else
+ tmp = strdup(name);
+
+ if (!tmp) {
+ free(master);
+ return NULL;
+ }
+
+ master->name = tmp;
+ master->nc = NULL;
+
+ master->recurse = 0;
+ master->depth = 0;
+ master->reading = 0;
+ master->read_fail = 0;
+ master->readall = 0;
+ master->default_ghost = flags & DAEMON_FLAGS_GHOST;
+ master->default_timeout = timeout;
+ master->default_logging = defaults_get_logging();
+ master->logopt = master->default_logging;
+
+ INIT_LIST_HEAD(&master->mounts);
+ INIT_LIST_HEAD(&master->completed);
+
+ return master;
+}
+
+static void master_add_amd_mount_section_mounts(struct master *master, time_t age)
+{
+ unsigned int m_logopt = master->logopt;
+ struct master_mapent *entry;
+ struct map_source *source;
+ unsigned int loglevel;
+ unsigned int logopt;
+ unsigned int flags;
+ char *argv[2];
+ char **paths;
+ int ret;
+ int i;
+
+ loglevel = conf_amd_get_log_options();
+
+ paths = conf_amd_get_mount_paths();
+ if (!paths)
+ return;
+
+ i = 0;
+ while (paths[i]) {
+ const char *path = paths[i];
+ unsigned int ghost = 0;
+ time_t timeout;
+ char *type = NULL;
+ char *map = NULL;
+ char *opts;
+
+ ret = master_partial_match_mapent(master, path);
+ if (ret) {
+ /* If this amd entry is already present in the
+ * master map it's not a duplicate, don't issue
+ * an error message.
+ */
+ if (ret == 1)
+ goto next;
+ info(m_logopt,
+ "amd section mount path conflict, %s ignored",
+ path);
+ goto next;
+ }
+
+ map = conf_amd_get_map_name(path);
+ if (!map) {
+ error(m_logopt,
+ "failed to get map name for amd section mount %s",
+ path);
+ goto next;
+ }
+
+ entry = master_new_mapent(master, path, age);
+ if (!entry) {
+ error(m_logopt,
+ "failed to allocate new amd section mount %s",
+ path);
+ goto next;
+ }
+
+ logopt = m_logopt;
+ if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
+ logopt = LOGOPT_DEBUG;
+ else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
+ logopt = LOGOPT_VERBOSE;
+
+ /* It isn't possible to provide the fullybrowsable amd
+ * browsing functionality within the autofs framework.
+ * This flag will not be set if browsable_dirs = full
+ * in the configuration or fullybrowsable is present as
+ * an option.
+ */
+ flags = conf_amd_get_flags(path);
+ if (flags & CONF_BROWSABLE_DIRS)
+ ghost = 1;
+
+ ret = master_add_autofs_point(entry, logopt, 0, ghost, 0);
+ if (!ret) {
+ error(m_logopt, "failed to add autofs_point");
+ master_free_mapent(entry);
+ goto next;
+ }
+
+ opts = conf_amd_get_map_options(path);
+ if (opts) {
+ /* autofs uses the equivalent of cache:=inc,sync
+ * (except for file maps which use cache:=all,sync)
+ * but if the map is large then it may be necessary
+ * to read the whole map at startup even if browsing
+ * is is not enabled, so look for cache:=all in the
+ * map_options configuration entry.
+ */
+ if (strstr(opts, "cache:=all"))
+ entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
+ free(opts);
+ }
+
+ type = conf_amd_get_map_type(path);
+ argv[0] = map;
+ argv[1] = NULL;
+
+ source = master_add_map_source(entry, type, "amd",
+ age, 1, (const char **) argv);
+ if (!source) {
+ error(m_logopt,
+ "failed to add source for amd section mount %s",
+ path);
+ master_free_mapent(entry);
+ goto next;
+ }
+
+ timeout = conf_amd_get_dismount_interval(path);
+ set_exp_timeout(entry->ap, source, timeout);
+ source->master_line = 0;
+
+ entry->age = age;
+ entry->current = NULL;
+
+ master_add_mapent(master, entry);
+next:
+ if (type)
+ free(type);
+ if (map)
+ free(map);
+ i++;
+ }
+
+ i = 0;
+ while (paths[i])
+ free(paths[i++]);
+ free(paths);
+}
+
+static void wait_for_lookups_and_lock(struct master *master)
+{
+ struct list_head *p, *head;
+ int status;
+
+again:
+ master_mutex_lock();
+
+ head = &master->mounts;
+ p = head->next;
+ while (p != head) {
+ struct master_mapent *this;
+
+ this = list_entry(p, struct master_mapent, list);
+
+ status = pthread_rwlock_trywrlock(&this->source_lock);
+ if (status) {
+ struct timespec t = { 0, 200000000 };
+ struct timespec r;
+
+ master_mutex_unlock();
+
+ while (nanosleep(&t, &r) == -1 && errno == EINTR)
+ memcpy(&t, &r, sizeof(struct timespec));
+
+ goto again;
+ }
+ master_source_unlock(this);
+
+ p = p->next;
+ }
+}
+
+int master_read_master(struct master *master, time_t age)
+{
+ unsigned int logopt = master->logopt;
+ struct mapent_cache *nc;
+
+ /*
+ * We need to clear and re-populate the null map entry cache
+ * before alowing anyone else to use it.
+ */
+ wait_for_lookups_and_lock(master);
+ if (master->nc) {
+ cache_writelock(master->nc);
+ nc = master->nc;
+ cache_clean_null_cache(nc);
+ } else {
+ nc = cache_init_null_cache(master);
+ if (!nc) {
+ error(logopt,
+ "failed to init null map cache for %s",
+ master->name);
+ return 0;
+ }
+ cache_writelock(nc);
+ master->nc = nc;
+ }
+ master_init_scan();
+ lookup_nss_read_master(master, age);
+ cache_unlock(nc);
+ master_add_amd_mount_section_mounts(master, age);
+
+ if (!master->read_fail)
+ master_mount_mounts(master, age);
+ else {
+ master->read_fail = 0;
+ /* HUP signal sets master->readall == 1 only */
+ if (!master->readall) {
+ master_mutex_unlock();
+ return 0;
+ } else
+ master_mount_mounts(master, age);
+ }
+
+ if (list_empty(&master->mounts))
+ warn(logopt, "no mounts in table");
+
+ master_mutex_unlock();
+
+ return 1;
+}
+
+int master_submount_list_empty(struct autofs_point *ap)
+{
+ int res = 0;
+
+ mounts_mutex_lock(ap);
+ if (list_empty(&ap->submounts))
+ res = 1;
+ mounts_mutex_unlock(ap);
+
+ return res;
+}
+
+int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
+{
+ struct mnt_list *this, *sbmnt;
+ int ret = 1;
+
+ this = mnts_find_submount(path);
+ if (this) {
+ /* We have found a submount to expire */
+ st_mutex_lock();
+
+ if (this->ap->state == ST_SHUTDOWN) {
+ this = NULL;
+ st_mutex_unlock();
+ goto done;
+ }
+
+ this->ap->shutdown = ap->shutdown;
+
+ __st_add_task(this->ap, state);
+
+ st_mutex_unlock();
+
+ st_wait_task(this->ap, state, 0);
+
+ /*
+ * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
+ * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
+ * to ST_READY.
+ */
+ st_mutex_lock();
+ while ((sbmnt = mnts_find_submount(path))) {
+ struct timespec t = { 0, 300000000 };
+ struct timespec r;
+
+ if (sbmnt->ap->state != ST_SHUTDOWN &&
+ sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
+ sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
+ ret = 0;
+ mnts_put_mount(sbmnt);
+ break;
+ }
+ mnts_put_mount(sbmnt);
+
+ st_mutex_unlock();
+ while (nanosleep(&t, &r) == -1 && errno == EINTR)
+ memcpy(&t, &r, sizeof(struct timespec));
+ st_mutex_lock();
+ }
+ st_mutex_unlock();
+done:
+ mnts_put_mount(this);
+ }
+
+ return ret;
+}
+
+void master_notify_state_change(struct master *master, int sig)
+{
+ struct master_mapent *entry;
+ struct autofs_point *ap;
+ struct list_head *p;
+ int cur_state;
+ unsigned int logopt;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+ master_mutex_lock();
+
+ list_for_each(p, &master->mounts) {
+ enum states next = ST_INVAL;
+
+ entry = list_entry(p, struct master_mapent, list);
+
+ ap = entry->ap;
+ logopt = ap->logopt;
+
+ st_mutex_lock();
+
+ if (ap->state == ST_SHUTDOWN)
+ goto next;
+
+ switch (sig) {
+ case SIGTERM:
+ case SIGINT:
+ if (ap->state != ST_SHUTDOWN_PENDING &&
+ ap->state != ST_SHUTDOWN_FORCE) {
+ next = ST_SHUTDOWN_PENDING;
+ ap->shutdown = 1;
+ __st_add_task(ap, next);
+ }
+ break;
+#ifdef ENABLE_FORCED_SHUTDOWN
+ case SIGUSR2:
+ if (ap->state != ST_SHUTDOWN_FORCE &&
+ ap->state != ST_SHUTDOWN_PENDING) {
+ next = ST_SHUTDOWN_FORCE;
+ ap->shutdown = 1;
+ __st_add_task(ap, next);
+ }
+ break;
+#endif
+ case SIGUSR1:
+ assert(ap->state == ST_READY);
+ next = ST_PRUNE;
+ __st_add_task(ap, next);
+ break;
+ }
+next:
+ if (next != ST_INVAL)
+ debug(logopt,
+ "sig %d switching %s from %d to %d",
+ sig, ap->path, ap->state, next);
+
+ st_mutex_unlock();
+ }
+
+ master_mutex_unlock();
+ pthread_setcancelstate(cur_state, NULL);
+
+ return;
+}
+
+static int master_do_mount(struct master_mapent *entry)
+{
+ struct startup_cond suc;
+ struct autofs_point *ap;
+ pthread_t thid;
+ int status;
+
+ ap = entry->ap;
+
+ if (handle_mounts_startup_cond_init(&suc)) {
+ crit(ap->logopt,
+ "failed to init startup cond for mount %s", entry->path);
+ return 0;
+ }
+
+ suc.ap = ap;
+ suc.root = ap->path;
+ suc.done = 0;
+ suc.status = 0;
+
+ if (!(do_force_unlink & UNLINK_AND_EXIT))
+ debug(ap->logopt, "mounting %s", entry->path);
+
+ status = pthread_create(&thid, &th_attr, handle_mounts, &suc);
+ if (status) {
+ crit(ap->logopt,
+ "failed to create mount handler thread for %s",
+ entry->path);
+ handle_mounts_startup_cond_destroy(&suc);
+ return 0;
+ }
+
+ while (!suc.done) {
+ status = pthread_cond_wait(&suc.cond, &suc.mutex);
+ if (status)
+ fatal(status);
+ }
+
+ if (suc.status) {
+ if (!(do_force_unlink & UNLINK_AND_EXIT))
+ error(ap->logopt, "failed to startup mount");
+ handle_mounts_startup_cond_destroy(&suc);
+ return 0;
+ }
+ entry->thid = thid;
+
+ handle_mounts_startup_cond_destroy(&suc);
+
+ return 1;
+}
+
+static void check_update_map_sources(struct master_mapent *entry, int readall)
+{
+ struct map_source *source, *last;
+ struct autofs_point *ap;
+ int map_stale = 0;
+
+ if (readall)
+ map_stale = 1;
+
+ ap = entry->ap;
+
+ master_source_writelock(entry);
+
+ last = NULL;
+ source = entry->maps;
+ while (source) {
+ if (readall)
+ source->stale = 1;
+
+ /*
+ * If a map source is no longer valid and all it's
+ * entries have expired away we can get rid of it.
+ */
+ if (entry->age > source->age) {
+ struct mapent *me;
+ cache_readlock(source->mc);
+ me = cache_lookup_first(source->mc);
+ if (!me) {
+ struct map_source *next = source->next;
+
+ cache_unlock(source->mc);
+
+ if (!last)
+ entry->maps = next;
+ else
+ last->next = next;
+
+ if (entry->maps == source)
+ entry->maps = next;
+
+ master_free_map_source(source, 1);
+
+ source = next;
+ continue;
+ } else {
+ source->stale = 1;
+ map_stale = 1;
+ }
+ cache_unlock(source->mc);
+ }
+ last = source;
+ source = source->next;
+ }
+
+ master_source_unlock(entry);
+
+ /* The map sources have changed */
+ if (map_stale)
+ st_add_task(ap, ST_READMAP);
+
+ return;
+}
+
+int master_mount_mounts(struct master *master, time_t age)
+{
+ struct mapent_cache *nc = master->nc;
+ struct list_head *p, *head;
+ int cur_state;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+
+ head = &master->mounts;
+ p = head->next;
+ while (p != head) {
+ struct master_mapent *this;
+ struct autofs_point *ap;
+ struct mapent *ne, *nested;
+ struct stat st;
+ int state_pipe, save_errno;
+ int ret;
+
+ this = list_entry(p, struct master_mapent, list);
+ p = p->next;
+
+ ap = this->ap;
+
+ /* A master map entry has gone away */
+ if (this->age < age) {
+ st_add_task(ap, ST_SHUTDOWN_PENDING);
+ continue;
+ }
+
+ cache_readlock(nc);
+ ne = cache_lookup_distinct(nc, this->path);
+ /*
+ * If this path matched a nulled entry the master map entry
+ * must be an indirect mount so the master map entry line
+ * number may be obtained from this->maps.
+ */
+ if (ne) {
+ int lineno = ne->age;
+ cache_unlock(nc);
+
+ /* null entry appears after map entry */
+ if (this->maps->master_line < lineno) {
+ warn(ap->logopt,
+ "ignoring null entry that appears after "
+ "existing entry for %s", this->path);
+ goto cont;
+ }
+ if (ap->state != ST_INIT) {
+ st_add_task(ap, ST_SHUTDOWN_PENDING);
+ continue;
+ }
+ /*
+ * The map entry hasn't been started yet and we've
+ * seen a preceeding null map entry for it so just
+ * delete it from the master map entry list so it
+ * doesn't get in the road.
+ */
+ list_del_init(&this->list);
+ master_free_mapent_sources(ap->entry, 1);
+ master_free_mapent(ap->entry);
+ continue;
+ }
+ nested = cache_partial_match(nc, this->path);
+ if (nested) {
+ error(ap->logopt,
+ "removing invalid nested null entry %s",
+ nested->key);
+ nested = cache_partial_match(nc, this->path);
+ if (nested)
+ cache_delete(nc, nested->key);
+ }
+ cache_unlock(nc);
+cont:
+ st_mutex_lock();
+
+ state_pipe = this->ap->state_pipe[1];
+
+ /* No pipe so mount is needed */
+ ret = fstat(state_pipe, &st);
+ save_errno = errno;
+
+ st_mutex_unlock();
+
+ if (!ret)
+ check_update_map_sources(this, master->readall);
+ else if (ret == -1 && save_errno == EBADF) {
+ if (!master_do_mount(this)) {
+ list_del_init(&this->list);
+ master_free_mapent_sources(ap->entry, 1);
+ master_free_mapent(ap->entry);
+ }
+ }
+ }
+
+ pthread_setcancelstate(cur_state, NULL);
+
+ return 1;
+}
+
+/* The nss source instances end up in reverse order. */
+static void list_source_instances(struct map_source *source, struct map_source *instance)
+{
+ if (!source || !instance) {
+ printf("none");
+ return;
+ }
+
+ if (instance->next)
+ list_source_instances(source, instance->next);
+
+ /*
+ * For convienience we map nss instance type "files" to "file".
+ * Check for that and report corrected instance type.
+ */
+ if (strcmp(instance->type, "file"))
+ printf("%s ", instance->type);
+ else {
+ if (source->argv && *(source->argv[0]) != '/')
+ printf("files ");
+ else
+ printf("%s ", instance->type);
+ }
+
+ return;
+}
+
+static void print_map_info(struct map_source *source)
+{
+ int argc = source->argc;
+ int i, multi, map_num;
+
+ multi = (source->type && !strcmp(source->type, "multi"));
+ map_num = 1;
+ for (i = 0; i < argc; i++) {
+ if (source->argv[i] && *source->argv[i] != '-') {
+ if (!multi)
+ printf(" map: %s\n", source->argv[i]);
+ else
+ printf(" map[%i]: %s\n", map_num, source->argv[i]);
+ i++;
+ }
+
+ if (i >= argc)
+ return;
+
+ if (!strcmp(source->argv[i], "--"))
+ continue;
+
+ if (source->argv[i]) {
+ int need_newline = 0;
+ int j;
+
+ if (!multi)
+ printf(" arguments:");
+ else
+ printf(" arguments[%i]:", map_num);
+
+ for (j = i; j < source->argc; j++) {
+ if (!strcmp(source->argv[j], "--"))
+ break;
+ printf(" %s", source->argv[j]);
+ i++;
+ need_newline = 1;
+ }
+ if (need_newline)
+ printf("\n");
+ }
+ if (multi)
+ map_num++;
+ }
+
+ return;
+}
+
+static int match_type(const char *source, const char *type)
+{
+ if (!strcmp(source, type))
+ return 1;
+ /* Sources file and files are synonymous */
+ if (!strncmp(source, type, 4) && (strlen(source) <= 5))
+ return 1;
+ return 0;
+}
+
+static char *get_map_name(const char *string)
+{
+ char *name, *tmp;
+ char *start, *end, *base;
+
+ tmp = strdup(string);
+ if (!tmp) {
+ printf("error: allocation failure: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ base = basename(tmp);
+ end = strchr(base, ',');
+ if (end)
+ *end = '\0';
+ start = strchr(tmp, '=');
+ if (start)
+ start++;
+ else {
+ char *colon = strrchr(base, ':');
+ if (colon)
+ start = ++colon;
+ else
+ start = base;
+ }
+
+ name = strdup(start);
+ if (!name)
+ printf("error: allocation failure: %s\n", strerror(errno));
+ free(tmp);
+
+ return name;
+}
+
+static int match_name(struct map_source *source, const char *name)
+{
+ int argc = source->argc;
+ int ret = 0;
+ int i;
+
+ /*
+ * This can't work for old style "multi" type sources since
+ * there's no way to know from which map the cache entry came
+ * from and duplicate entries are ignored at map read time.
+ * All we can really do is list all the entries for the given
+ * multi map if one of its map names matches.
+ */
+ for (i = 0; i < argc; i++) {
+ if (i == 0 || !strcmp(source->argv[i], "--")) {
+ if (i != 0) {
+ i++;
+ if (i >= argc)
+ break;
+ }
+
+ if (source->argv[i] && *source->argv[i] != '-') {
+ char *map = get_map_name(source->argv[i]);
+ if (!map)
+ break;
+ if (!strcmp(map, name)) {
+ ret = 1;
+ free(map);
+ break;
+ }
+ free(map);
+ }
+ }
+ }
+
+ return ret;
+}
+
+int dump_map(struct master *master, const char *type, const char *name)
+{
+ struct list_head *p, *head;
+
+ if (list_empty(&master->mounts)) {
+ printf("no master map entries found\n");
+ return 1;
+ }
+
+ head = &master->mounts;
+ p = head->next;
+ while (p != head) {
+ struct map_source *source;
+ struct master_mapent *this;
+ struct autofs_point *ap;
+ time_t now = monotonic_time(NULL);
+
+ this = list_entry(p, struct master_mapent, list);
+ p = p->next;
+
+ ap = this->ap;
+
+ /*
+ * Ensure we actually read indirect map entries so we can
+ * list them. The map reads won't read any indirect map
+ * entries (other than those in a file map) unless the
+ * browse option is set.
+ */
+ if (ap->type == LKP_INDIRECT)
+ ap->flags |= MOUNT_FLAG_GHOST;
+
+ /* Read the map content into the cache */
+ if (lookup_nss_read_map(ap, NULL, now))
+ lookup_prune_cache(ap, now);
+ else {
+ printf("failed to read map\n");
+ lookup_close_lookup(ap);
+ continue;
+ }
+
+ if (!this->maps) {
+ printf("no map sources found for %s\n", ap->path);
+ lookup_close_lookup(ap);
+ continue;
+ }
+
+ source = this->maps;
+ while (source) {
+ struct map_source *instance;
+ struct mapent *me;
+
+ instance = NULL;
+ if (source->type) {
+ if (!match_type(source->type, type)) {
+ source = source->next;
+ continue;
+ }
+ if (!match_name(source, name)) {
+ source = source->next;
+ continue;
+ }
+ instance = source;
+ } else {
+ struct map_source *map;
+
+ map = source->instance;
+ while (map) {
+ if (!match_type(map->type, type)) {
+ map = map->next;
+ continue;
+ }
+ if (!match_name(map, name)) {
+ map = map->next;
+ continue;
+ }
+ instance = map;
+ break;
+ }
+ }
+
+ if (!instance) {
+ source = source->next;
+ lookup_close_lookup(ap);
+ continue;
+ }
+
+ me = cache_lookup_first(source->mc);
+ if (!me)
+ printf("no keys found in map\n");
+ else {
+ do {
+ if (me->source == instance)
+ printf("%s\t%s\n", me->key, me->mapent);
+ } while ((me = cache_lookup_next(source->mc, me)));
+ }
+
+ lookup_close_lookup(ap);
+ return 1;
+ }
+ lookup_close_lookup(ap);
+ }
+
+ return 0;
+}
+
+int master_show_mounts(struct master *master)
+{
+ struct list_head *p, *head;
+
+ printf("\nautofs dump map information\n"
+ "===========================\n\n");
+
+ printf("global options: ");
+ if (!global_options)
+ printf("none configured\n");
+ else {
+ printf("%s\n", global_options);
+ unsigned int append_options = defaults_get_append_options();
+ const char *append = append_options ? "will" : "will not";
+ printf("global options %s be appended to map entries\n", append);
+ }
+
+ if (list_empty(&master->mounts)) {
+ printf("no master map entries found\n\n");
+ return 1;
+ }
+
+ head = &master->mounts;
+ p = head->next;
+ while (p != head) {
+ struct map_source *source;
+ struct master_mapent *this;
+ struct autofs_point *ap;
+ time_t now = monotonic_time(NULL);
+ unsigned int count = 0;
+
+ this = list_entry(p, struct master_mapent, list);
+ p = p->next;
+
+ ap = this->ap;
+
+ printf("\nMount point: %s\n", ap->path);
+
+ printf("\nsource(s):\n");
+
+ /*
+ * Ensure we actually read indirect map entries so we can
+ * list them. The map reads won't read any indirect map
+ * entries (other than those in a file map) unless the
+ * browse option is set.
+ */
+ if (ap->type == LKP_INDIRECT)
+ ap->flags |= MOUNT_FLAG_GHOST;
+
+ /* Read the map content into the cache */
+ if (lookup_nss_read_map(ap, NULL, now))
+ lookup_prune_cache(ap, now);
+ else {
+ printf(" failed to read map\n\n");
+ continue;
+ }
+
+ if (!this->maps) {
+ printf(" no map sources found\n\n");
+ continue;
+ }
+
+ source = this->maps;
+ while (source) {
+ struct mapent *me;
+
+ if (source->type)
+ printf("\n type: %s\n", source->type);
+ else {
+ printf("\n instance type(s): ");
+ list_source_instances(source, source->instance);
+ printf("\n");
+ }
+
+ if (source->argc >= 1) {
+ print_map_info(source);
+ if (count && ap->type == LKP_INDIRECT)
+ printf(" duplicate indirect map entry"
+ " will be ignored at run time\n");
+ }
+
+ printf("\n");
+
+ me = cache_lookup_first(source->mc);
+ if (!me)
+ printf(" no keys found in map\n");
+ else {
+ do {
+ printf(" %s | %s\n", me->key, me->mapent);
+ } while ((me = cache_lookup_next(source->mc, me)));
+ }
+
+ count++;
+
+ source = source->next;
+ }
+
+ lookup_close_lookup(ap);
+
+ printf("\n");
+ }
+
+ return 1;
+}
+
+int master_list_empty(struct master *master)
+{
+ int res = 0;
+
+ master_mutex_lock();
+ if (list_empty(&master->mounts))
+ res = 1;
+ master_mutex_unlock();
+
+ return res;
+}
+
+int master_done(struct master *master)
+{
+ struct list_head *head, *p;
+ struct master_mapent *entry;
+ int res = 0;
+
+ head = &master->completed;
+ p = head->next;
+ while (p != head) {
+ entry = list_entry(p, struct master_mapent, join);
+ p = p->next;
+ list_del(&entry->join);
+ pthread_join(entry->thid, NULL);
+ master_free_mapent_sources(entry, 1);
+ master_free_mapent(entry);
+ }
+ if (list_empty(&master->mounts))
+ res = 1;
+
+ return res;
+}
+
+unsigned int master_get_logopt(void)
+{
+ return master_list ? master_list->logopt : LOGOPT_NONE;
+}
+
+int master_kill(struct master *master)
+{
+ if (!list_empty(&master->mounts))
+ return 0;
+
+ if (master->name)
+ free(master->name);
+
+ cache_release_null_cache(master);
+ free(master);
+
+ return 1;
+}
--- /dev/null
+++ autofs-5.1.4/daemon/master_parse.y
@@ -0,0 +1,983 @@
+%{
+/* ----------------------------------------------------------------------- *
+ *
+ * master_parser.y - master map buffer parser.
+ *
+ * Copyright 2006 Ian Kent <raven@themaw.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+
+#include "automount.h"
+#include "master.h"
+
+#define MAX_ERR_LEN 512
+
+extern struct master *master_list;
+
+char **add_argv(int, char **, char *);
+const char **copy_argv(int, const char **);
+int free_argv(int, const char **);
+
+extern FILE *master_in;
+extern char *master_text;
+extern int master_lex(void);
+extern int master_lineno;
+extern void master_set_scan_buffer(const char *);
+
+static char *master_strdup(char *);
+static void local_init_vars(void);
+static void local_free_vars(void);
+static void trim_maptype(char *);
+static int add_multi_mapstr(void);
+
+static int master_error(const char *s);
+static int master_notify(const char *s);
+static int master_msg(const char *s);
+
+static char *path;
+static char *type;
+static char *format;
+static long timeout;
+static long negative_timeout;
+static unsigned symlnk;
+static unsigned strictexpire;
+static unsigned nobind;
+static unsigned ghost;
+extern unsigned global_selection_options;
+static unsigned random_selection;
+static unsigned use_weight;
+static unsigned long mode;
+static char **tmp_argv;
+static int tmp_argc;
+static char **local_argv;
+static int local_argc;
+
+#define PROPAGATION_SHARED MOUNT_FLAG_SHARED
+#define PROPAGATION_SLAVE MOUNT_FLAG_SLAVE
+#define PROPAGATION_PRIVATE MOUNT_FLAG_PRIVATE
+#define PROPAGATION_MASK (MOUNT_FLAG_SHARED | \
+ MOUNT_FLAG_SLAVE | \
+ MOUNT_FLAG_PRIVATE)
+static unsigned int propagation;
+
+static char errstr[MAX_ERR_LEN];
+
+static unsigned int verbose;
+static unsigned int debug;
+
+static int lineno;
+
+#define YYDEBUG 0
+
+#ifndef YYENABLE_NLS
+#define YYENABLE_NLS 0
+#endif
+#ifndef YYLTYPE_IS_TRIVIAL
+#define YYLTYPE_IS_TRIVIAL 0
+#endif
+
+#if YYDEBUG
+static int master_fprintf(FILE *, char *, ...);
+#undef YYFPRINTF
+#define YYFPRINTF master_fprintf
+#endif
+
+%}
+
+%union {
+ char strtype[2048];
+ int inttype;
+ long longtype;
+}
+
+%token COMMENT
+%token MAP
+%token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOBIND OPT_NOGHOST OPT_GHOST OPT_VERBOSE
+%token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT OPT_SYMLINK OPT_MODE
+%token OPT_STRICTEXPIRE OPT_SHARED OPT_SLAVE OPT_PRIVATE
+%token COLON COMMA NL DDASH
+%type <strtype> map
+%type <strtype> options
+%type <strtype> dn
+%type <strtype> dnattrs
+%type <strtype> dnattr
+%type <strtype> option
+%type <strtype> daemon_option
+%type <strtype> mount_option
+%token <strtype> PATH
+%token <strtype> QUOTE
+%token <strtype> NILL
+%token <strtype> SPACE
+%token <strtype> EQUAL
+%token <strtype> MULTITYPE
+%token <strtype> MAPTYPE
+%token <strtype> DNSERVER
+%token <strtype> DNATTR
+%token <strtype> DNNAME
+%token <strtype> MAPHOSTS
+%token <strtype> MAPNULL
+%token <strtype> MAPXFN
+%token <strtype> MAPNAME
+%token <longtype> NUMBER
+%token <longtype> OCTALNUMBER
+%token <strtype> OPTION
+
+%start file
+
+%%
+
+file: {
+ master_lineno = 0;
+#if YYDEBUG != 0
+ master_debug = YYDEBUG;
+#endif
+ } line
+ ;
+
+line:
+ | PATH mapspec
+ {
+ path = master_strdup($1);
+ if (!path) {
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | PATH MULTITYPE maplist
+ {
+ char *tmp = NULL;
+
+ trim_maptype($2);
+
+ if (path)
+ free(path);
+ path = master_strdup($1);
+ if (!path) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+
+ if ((tmp = strchr($2, ',')))
+ *tmp++ = '\0';
+#ifndef WITH_HESIOD
+ /* Map type or map type parser is hesiod */
+ if (!strcmp($2, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
+ master_error("hesiod support not built in");
+ local_free_vars();
+ YYABORT;
+ }
+#endif
+ if (type)
+ free(type);
+ type = master_strdup($2);
+ if (!type) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ if (tmp) {
+ if (format)
+ free(format);
+ format = master_strdup(tmp);
+ if (!format) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ }
+ | PATH COLON { master_notify($1); YYABORT; }
+ | PATH OPTION { master_notify($2); YYABORT; }
+ | PATH NILL { master_notify($2); YYABORT; }
+ | PATH OPT_RANDOM { master_notify($1); YYABORT; }
+ | PATH OPT_USE_WEIGHT { master_notify($1); YYABORT; }
+ | PATH OPT_DEBUG { master_notify($1); YYABORT; }
+ | PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
+ | PATH OPT_SYMLINK { master_notify($1); YYABORT; }
+ | PATH OPT_STRICTEXPIRE { master_notify($1); YYABORT; }
+ | PATH OPT_SHARED { master_notify($1); YYABORT; }
+ | PATH OPT_SLAVE { master_notify($1); YYABORT; }
+ | PATH OPT_PRIVATE { master_notify($1); YYABORT; }
+ | PATH OPT_NOBIND { master_notify($1); YYABORT; }
+ | PATH OPT_GHOST { master_notify($1); YYABORT; }
+ | PATH OPT_NOGHOST { master_notify($1); YYABORT; }
+ | PATH OPT_VERBOSE { master_notify($1); YYABORT; }
+ | PATH OPT_MODE { master_notify($1); YYABORT; }
+ | PATH { master_notify($1); YYABORT; }
+ | QUOTE { master_notify($1); YYABORT; }
+ | OPTION { master_notify($1); YYABORT; }
+ | NILL { master_notify($1); YYABORT; }
+ | COMMENT { YYABORT; }
+ ;
+
+mapspec: map
+ {
+ if (local_argv)
+ free_argv(local_argc, (const char **) local_argv);
+ local_argc = tmp_argc;
+ local_argv = tmp_argv;
+ tmp_argc = 0;
+ tmp_argv = NULL;
+ }
+ | map options
+ {
+ if (local_argv)
+ free_argv(local_argc, (const char **) local_argv);
+ local_argc = tmp_argc;
+ local_argv = tmp_argv;
+ tmp_argc = 0;
+ tmp_argv = NULL;
+ }
+ ;
+
+maplist: map
+ {
+ if (!add_multi_mapstr()) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | map options
+ {
+ if (!add_multi_mapstr()) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | maplist DDASH map
+ {
+ local_argc++;
+ local_argv = add_argv(local_argc, local_argv, "--");
+ if (!local_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ if (!add_multi_mapstr()) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | maplist DDASH map options
+ {
+ local_argc++;
+ local_argv = add_argv(local_argc, local_argv, "--");
+ if (!local_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ if (!add_multi_mapstr()) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ ;
+
+map: PATH
+ {
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+ if (!tmp_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | MAPNAME
+ {
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+ if (!tmp_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | MAPHOSTS
+ {
+ if (type)
+ free(type);
+ type = master_strdup($1 + 1);
+ if (!type) {
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | MAPXFN
+ {
+ master_notify($1);
+ master_msg("X/Open Federated Naming service not supported");
+ YYABORT;
+ }
+ | MAPNULL
+ {
+ if (type)
+ free(type);
+ type = master_strdup($1 + 1);
+ if (!type) {
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | dnattrs
+ {
+ if (type)
+ free(type);
+ type = master_strdup("ldap");
+ if (!type) {
+ local_free_vars();
+ YYABORT;
+ }
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+ if (!tmp_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | MAPTYPE PATH
+ {
+ char *tmp = NULL;
+
+ trim_maptype($1);
+
+ if ((tmp = strchr($1, ',')))
+ *tmp++ = '\0';
+#ifndef WITH_HESIOD
+ /* Map type or map type parser is hesiod */
+ if (!strcmp($1, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
+ master_error("hesiod support not built in");
+ local_free_vars();
+ YYABORT;
+ }
+#endif
+ if (type)
+ free(type);
+ if (strcmp($1, "exec"))
+ type = master_strdup($1);
+ else
+ type = master_strdup("program");
+ if (!type) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ if (tmp) {
+ if (format)
+ free(format);
+ format = master_strdup(tmp);
+ if (!format) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
+ if (!tmp_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | MAPTYPE MAPNAME
+ {
+ char *tmp = NULL;
+
+ trim_maptype($1);
+
+ if ((tmp = strchr($1, ',')))
+ *tmp++ = '\0';
+
+ if (type)
+ free(type);
+ if (strcmp($1, "exec"))
+ type = master_strdup($1);
+ else
+ type = master_strdup("program");
+ if (!type) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ if (tmp) {
+ if (format)
+ free(format);
+ format = master_strdup(tmp);
+ if (!format) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
+ if (!tmp_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | MAPTYPE dn
+ {
+ char *tmp = NULL;
+
+ trim_maptype($1);
+
+ if ((tmp = strchr($1, ',')))
+ *tmp++ = '\0';
+
+ if (type)
+ free(type);
+ if (strcmp($1, "exec"))
+ type = master_strdup($1);
+ else
+ type = master_strdup("program");
+ if (!type) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ if (tmp) {
+ if (format)
+ free(format);
+ format = master_strdup(tmp);
+ if (!format) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
+ if (!tmp_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ /* Add back the type for lookup_ldap.c to handle ldaps */
+ if (*tmp_argv[0]) {
+ tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2);
+ if (!tmp) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ strcpy(tmp, type);
+ strcat(tmp, ":");
+ strcat(tmp, tmp_argv[0]);
+ free(tmp_argv[0]);
+ tmp_argv[0] = tmp;
+ }
+ }
+ ;
+
+dn: DNSERVER dnattrs
+ {
+ strcpy($$, $1);
+ strcat($$, $2);
+ }
+ | dnattrs
+ {
+ strcpy($$, $1);
+ }
+ |
+ {
+ master_notify("syntax error in dn");
+ YYABORT;
+ }
+ ;
+
+dnattrs: DNATTR EQUAL DNNAME
+ {
+ if (strcasecmp($1, "cn") &&
+ strcasecmp($1, "ou") &&
+ strcasecmp($1, "automountMapName") &&
+ strcasecmp($1, "nisMapName")) {
+ strcpy(errstr, $1);
+ strcat(errstr, "=");
+ strcat(errstr, $3);
+ master_notify(errstr);
+ YYABORT;
+ }
+ strcpy($$, $1);
+ strcat($$, "=");
+ strcat($$, $3);
+ }
+ | DNATTR EQUAL DNNAME COMMA dnattr
+ {
+ if (strcasecmp($1, "cn") &&
+ strcasecmp($1, "ou") &&
+ strcasecmp($1, "automountMapName") &&
+ strcasecmp($1, "nisMapName")) {
+ strcpy(errstr, $1);
+ strcat(errstr, "=");
+ strcat(errstr, $3);
+ master_notify(errstr);
+ YYABORT;
+ }
+ strcpy($$, $1);
+ strcat($$, "=");
+ strcat($$, $3);
+ strcat($$, ",");
+ strcat($$, $5);
+ }
+ | DNNAME
+ {
+ /* Matches map in old style syntax ldap:server:map */
+ strcpy($$, $1);
+ }
+ | DNATTR
+ {
+ master_notify($1);
+ YYABORT;
+ }
+ ;
+
+dnattr: DNATTR EQUAL DNNAME
+ {
+ if (!strcasecmp($1, "automountMapName") ||
+ !strcasecmp($1, "nisMapName")) {
+ strcpy(errstr, $1);
+ strcat(errstr, "=");
+ strcat(errstr, $3);
+ master_notify(errstr);
+ YYABORT;
+ }
+ strcpy($$, $1);
+ strcat($$, "=");
+ strcat($$, $3);
+ }
+ | DNATTR EQUAL DNNAME COMMA dnattr
+ {
+ if (!strcasecmp($1, "automountMapName") ||
+ !strcasecmp($1, "nisMapName")) {
+ strcpy(errstr, $1);
+ strcat(errstr, "=");
+ strcat(errstr, $3);
+ master_notify(errstr);
+ YYABORT;
+ }
+ strcpy($$, $1);
+ strcat($$, "=");
+ strcat($$, $3);
+ strcat($$, ",");
+ strcat($$, $5);
+ }
+ | DNATTR
+ {
+ master_notify($1);
+ YYABORT;
+ }
+ | DNNAME
+ {
+ master_notify($1);
+ YYABORT;
+ }
+ ;
+
+options: option {}
+ | options COMMA option {}
+ | options option {}
+ | options COMMA COMMA option
+ {
+ master_notify($1);
+ YYABORT;
+ }
+ | options EQUAL
+ {
+ master_notify($1);
+ YYABORT;
+ }
+ ;
+
+option: daemon_option
+ | mount_option {}
+ | error
+ {
+ master_notify("bogus option");
+ YYABORT;
+ }
+ ;
+
+daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; }
+ | OPT_NTIMEOUT NUMBER { negative_timeout = $2; }
+ | OPT_SYMLINK { symlnk = 1; }
+ | OPT_STRICTEXPIRE { strictexpire = 1; }
+ | OPT_SHARED { propagation = PROPAGATION_SHARED; }
+ | OPT_SLAVE { propagation = PROPAGATION_SLAVE; }
+ | OPT_PRIVATE { propagation = PROPAGATION_PRIVATE; }
+ | OPT_NOBIND { nobind = 1; }
+ | OPT_NOGHOST { ghost = 0; }
+ | OPT_GHOST { ghost = 1; }
+ | OPT_VERBOSE { verbose = 1; }
+ | OPT_DEBUG { debug = 1; }
+ | OPT_RANDOM { random_selection = 1; }
+ | OPT_USE_WEIGHT { use_weight = 1; }
+ | OPT_MODE OCTALNUMBER { mode = $2; }
+ ;
+
+mount_option: OPTION
+ {
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+ if (!tmp_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ ;
+%%
+
+#if YYDEBUG
+static int master_fprintf(FILE *f, char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+ vsyslog(LOG_DEBUG, msg, ap);
+ va_end(ap);
+ return 1;
+}
+#endif
+
+static char *master_strdup(char *str)
+{
+ char *tmp;
+
+ tmp = strdup(str);
+ if (!tmp)
+ master_error("memory allocation error");
+ return tmp;
+}
+
+static int master_error(const char *s)
+{
+ logmsg("%s while parsing map.", s);
+ return 0;
+}
+
+static int master_notify(const char *s)
+{
+ logmsg("syntax error in map near [ %s ]", s);
+ return(0);
+}
+
+static int master_msg(const char *s)
+{
+ logmsg("%s", s);
+ return 0;
+}
+
+static void local_init_vars(void)
+{
+ path = NULL;
+ type = NULL;
+ format = NULL;
+ verbose = 0;
+ debug = 0;
+ timeout = -1;
+ negative_timeout = 0;
+ symlnk = 0;
+ strictexpire = 0;
+ propagation = PROPAGATION_SLAVE;
+ nobind = 0;
+ ghost = defaults_get_browse_mode();
+ random_selection = global_selection_options & MOUNT_FLAG_RANDOM_SELECT;
+ use_weight = 0;
+ mode = 0;
+ tmp_argv = NULL;
+ tmp_argc = 0;
+ local_argv = NULL;
+ local_argc = 0;
+}
+
+static void local_free_vars(void)
+{
+ if (path)
+ free(path);
+
+ if (type)
+ free(type);
+
+ if (format)
+ free(format);
+
+ if (local_argv) {
+ free_argv(local_argc, (const char **) local_argv);
+ local_argv = NULL;
+ local_argc = 0;
+ }
+
+ if (tmp_argv) {
+ free_argv(tmp_argc, (const char **) tmp_argv);
+ tmp_argv = NULL;
+ tmp_argc = 0;
+ }
+}
+
+static void trim_maptype(char *type)
+{
+ char *tmp;
+
+ tmp = strchr(type, ':');
+ if (tmp)
+ *tmp = '\0';
+ else {
+ int len = strlen(type);
+ while (len-- && isblank(type[len]))
+ type[len] = '\0';
+ }
+ return;
+}
+
+static int add_multi_mapstr(void)
+{
+ if (type) {
+ /* If type given and format is non-null add it back */
+ if (format) {
+ int len = strlen(type) + strlen(format) + 2;
+ char *tmp = realloc(type, len);
+ if (!tmp)
+ return 0;
+ type = tmp;
+ strcat(type, ",");
+ strcat(type, format);
+ free(format);
+ format = NULL;
+ }
+
+ local_argc++;
+ local_argv = add_argv(local_argc, local_argv, type);
+ if (!local_argv) {
+ free(type);
+ type = NULL;
+ return 0;
+ }
+
+ free(type);
+ type = NULL;
+ }
+
+ local_argv = append_argv(local_argc, local_argv, tmp_argc, tmp_argv);
+ if (!local_argv) {
+ free(type);
+ type = NULL;
+ return 0;
+ }
+ local_argc += tmp_argc;
+
+ tmp_argc = 0;
+ tmp_argv = NULL;
+
+ return 1;
+}
+
+void master_init_scan(void)
+{
+ lineno = 0;
+}
+
+int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigned int logging, time_t age)
+{
+ struct master *master = master_list;
+ struct mapent_cache *nc;
+ struct master_mapent *entry, *new;
+ struct map_source *source;
+ unsigned int logopt = logging;
+ unsigned int m_logopt = master->logopt;
+ size_t mp_len;
+ int ret;
+
+ local_init_vars();
+
+ lineno++;
+
+ master_set_scan_buffer(buffer);
+
+ ret = master_parse();
+ if (ret != 0) {
+ local_free_vars();
+ return 0;
+ }
+
+ mp_len = strlen(path);
+ while (mp_len && path[--mp_len] == '/')
+ path[mp_len] = 0;
+
+ nc = master->nc;
+
+ /* Add null map entries to the null map cache */
+ if (type && !strcmp(type, "null")) {
+ cache_update(nc, NULL, path, NULL, lineno);
+ local_free_vars();
+ return 1;
+ }
+
+ /* Ignore all subsequent matching nulled entries */
+ if (cache_lookup_distinct(nc, path)) {
+ local_free_vars();
+ return 1;
+ }
+
+ if (debug || verbose) {
+ logopt = (debug ? LOGOPT_DEBUG : 0);
+ logopt |= (verbose ? LOGOPT_VERBOSE : 0);
+ }
+
+ new = NULL;
+ entry = master_find_mapent(master, path);
+ if (!entry) {
+ new = master_new_mapent(master, path, age);
+ if (!new) {
+ local_free_vars();
+ return 0;
+ }
+ entry = new;
+ } else {
+ if (entry->age && entry->age == age) {
+ if (strcmp(path, "/-")) {
+ info(m_logopt,
+ "ignoring duplicate indirect mount %s",
+ path);
+ local_free_vars();
+ return 0;
+ }
+ }
+ }
+
+ if (!format) {
+ if (conf_amd_mount_section_exists(path))
+ format = strdup("amd");
+ }
+
+ if (format && !strcmp(format, "amd")) {
+ unsigned int loglevel = conf_amd_get_log_options();
+ unsigned int flags = conf_amd_get_flags(path);
+
+ if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
+ logopt = LOGOPT_DEBUG;
+ else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
+ logopt = LOGOPT_VERBOSE;
+
+ /* It isn't possible to provide the fullybrowsable amd
+ * browsing functionality within the autofs framework.
+ * This flag will not be set if browsable_dirs = full
+ * in the configuration or fullybrowsable is present as
+ * an option.
+ */
+ if (flags & CONF_BROWSABLE_DIRS)
+ ghost = 1;
+ }
+
+ if (!entry->ap) {
+ ret = master_add_autofs_point(entry, logopt, nobind, ghost, 0);
+ if (!ret) {
+ error(m_logopt, "failed to add autofs_point");
+ if (new)
+ master_free_mapent(new);
+ local_free_vars();
+ return 0;
+ }
+ }
+ entry->ap->flags &= ~(PROPAGATION_MASK);
+ entry->ap->flags |= propagation;
+
+ if (random_selection)
+ entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
+ if (use_weight)
+ entry->ap->flags |= MOUNT_FLAG_USE_WEIGHT_ONLY;
+ if (symlnk)
+ entry->ap->flags |= MOUNT_FLAG_SYMLINK;
+ if (strictexpire)
+ entry->ap->flags |= MOUNT_FLAG_STRICTEXPIRE;
+ if (negative_timeout)
+ entry->ap->negative_timeout = negative_timeout;
+ if (mode && mode < LONG_MAX)
+ entry->ap->mode = mode;
+
+ if (timeout < 0) {
+ /*
+ * If no timeout is given get the timout from the
+ * autofs point, or the first map, or the config
+ * for amd maps.
+ */
+ if (format && !strcmp(format, "amd"))
+ timeout = conf_amd_get_dismount_interval(path);
+ else
+ timeout = get_exp_timeout(entry->ap, entry->maps);
+ }
+
+ if (format && !strcmp(format, "amd")) {
+ char *opts = conf_amd_get_map_options(path);
+ if (opts) {
+ /* autofs uses the equivalent of cache:=inc,sync
+ * (except for file maps which use cache:=all,sync)
+ * but if the map is large then it may be necessary
+ * to read the whole map at startup even if browsing
+ * is is not enabled, so look for cache:=all in the
+ * map_options configuration entry.
+ */
+ if (strstr(opts, "cache:=all"))
+ entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
+ free(opts);
+ }
+ }
+
+/*
+ source = master_find_map_source(entry, type, format,
+ local_argc, (const char **) local_argv);
+ if (!source)
+ source = master_add_map_source(entry, type, format, age,
+ local_argc, (const char **) local_argv);
+ else
+ source->age = age;
+*/
+ source = master_add_map_source(entry, type, format, age,
+ local_argc, (const char **) local_argv);
+ if (!source) {
+ error(m_logopt, "failed to add source");
+ if (new)
+ master_free_mapent(new);
+ local_free_vars();
+ return 0;
+ }
+ set_exp_timeout(entry->ap, source, timeout);
+ source->master_line = lineno;
+
+ entry->age = age;
+ entry->current = NULL;
+
+ if (new)
+ master_add_mapent(master, entry);
+
+ local_free_vars();
+
+ return 1;
+}
+
--- /dev/null
+++ autofs-5.1.4/daemon/master_tok.l
@@ -0,0 +1,504 @@
+%{
+/* ----------------------------------------------------------------------- *
+ *
+ * master_tok.l - master map tokenizer.
+ *
+ * Copyright 2006 Ian Kent <raven@themaw.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifdef ECHO
+# undef ECHO
+#endif /* ECHO */
+static void master_echo(void); /* forward definition */
+#define ECHO master_echo()
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "master_parse.tab.h"
+
+/*
+ * There are some things that need to be defined only if useing GNU flex.
+ * These must not be defined if using standard lex
+ */
+#ifdef FLEX_SCANNER
+int master_lineno;
+#endif
+
+int master_lex(void);
+int master_wrap(void);
+
+/* no need for yywrap() */
+#define YY_SKIP_YYWRAP
+
+#ifndef YY_STACK_USED
+#define YY_STACK_USED 0
+#endif
+#ifndef YY_ALWAYS_INTERACTIVE
+#define YY_ALWAYS_INTERACTIVE 0
+#endif
+#ifndef YY_NEVER_INTERACTIVE
+#define YY_NEVER_INTERACTIVE 0
+#endif
+#ifndef YY_MAIN
+#define YY_MAIN 0
+#endif
+
+void master_set_scan_buffer(const char *);
+const char *line = NULL;
+
+#ifdef FLEX_SCANNER
+const char *line_pos = NULL;
+const char *line_lim = NULL;
+int my_yyinput(char *, int);
+
+#undef YY_INPUT
+#define YY_INPUT(b, r, ms) (r = my_yyinput(b, ms))
+#else
+#undef input
+#undef unput
+#define input() (*(char *) line++)
+#define unput(c) (*(char *) --line = c)
+#endif
+
+#define BUFF_LEN 1024
+char buff[BUFF_LEN];
+char *bptr;
+char *optr = buff;
+unsigned int tlen;
+
+%}
+
+%option nounput
+
+%x PATHSTR MAPSTR DNSTR OPTSTR OCTAL
+
+WS [[:blank:]]+
+OPTWS [[:blank:]]*
+NL \r?\n
+CONT \\\n{OPTWS}
+
+OPTIONSTR ([\-]?([[:alpha:]_]([[:alnum:]_\-])*(=(\"?([[:alnum:]_\-\:\.])+\"?))?)+)
+MACROSTR (-D{OPTWS}([[:alpha:]_]([[:alnum:]_\-\.])*)=([[:alnum:]_\-\.])+)
+SLASHIFYSTR (--(no-)?slashify-colons)
+NUMBER [0-9]+
+OCTALNUMBER [0-7]+
+
+DNSERVSTR1 ([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:)
+DNSERVSTR2 (\[([[:xdigit:]]:.)+\](:[0-9]+)?:)
+DNSERVSTR3 (\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
+DNSERVSTR4 (\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/)
+DNSERVSTR5 (([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
+DNSERVSTR6 (\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
+DNSERVERSTR ({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6})
+
+AT_CN ([cC][[nN])
+AT_NMN ([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE])
+AT_AMN ([aA][uU][tT][oO][mM][oO][uU][nN][tT][Mm][aA][pP][Nn][aA][mM][eE])
+AT_OU ([oO][[uU])
+AT_DC ([dD][[cC])
+AT_O ([oO])
+AT_C ([cC])
+AT_L ([lL])
+DNATTRSTR ({AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}|{AT_L})
+DNNAMESTR1 ([[:alnum:]_.\- ]+)
+DNNAMESTR2 ([[:alnum:]_.\-]+)
+
+INTMAP (-hosts|-null)
+MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
+MULTISEP ([\-]{2}[[:blank:]]+)
+MTYPE ((file|program|exec|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS}))
+
+
+OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
+OPTNTOUT (-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeout{OPTWS}={OPTWS})
+
+MODE (--mode{OPTWS}|--mode{OPTWS}={OPTWS})
+
+%%
+
+<INITIAL>{
+ {NL} |
+ \x00 {
+ if (optr != buff) {
+ *optr = '\0';
+ strcpy(master_lval.strtype, buff);
+ return NILL;
+ }
+ }
+
+ #.* { return COMMENT; }
+
+ "/" {
+ if (optr != buff) {
+ *optr = '\0';
+ strcpy(master_lval.strtype, buff);
+ return NILL;
+ }
+ BEGIN(PATHSTR);
+ bptr = buff;
+ yyless(0);
+ }
+
+ . { *optr++ = *master_text; }
+}
+
+<PATHSTR>{
+ \x00 {
+ BEGIN(INITIAL);
+ *bptr++ = *master_text;
+ strcpy(master_lval.strtype, buff);
+ return NILL;
+ }
+
+ \\. { *bptr++ = *(master_text + 1); }
+ \" {
+ BEGIN(INITIAL);
+ *bptr++ = *master_text;
+ *bptr = '\0';
+ strcpy(master_lval.strtype, buff);
+ return QUOTE;
+ }
+
+ {WS} {
+ BEGIN(MAPSTR);
+ *bptr = '\0';
+ strcpy(master_lval.strtype, buff);
+ bptr = buff;
+ memset(buff, 0, BUFF_LEN);
+ return(PATH);
+ }
+
+ <<EOF>> {
+ BEGIN(INITIAL);
+ *bptr = '\0';
+ strcpy(master_lval.strtype, buff);
+ return(PATH);
+ }
+
+ {NL} {
+ BEGIN(INITIAL);
+ *bptr = '\0';
+ strcpy(master_lval.strtype, buff);
+ return PATH;
+ }
+
+ . { *bptr++ = *master_text; }
+}
+
+<MAPSTR>{
+ {OPTWS}\\\n{OPTWS} {}
+
+ {MULTI} {
+ tlen = master_leng - 1;
+ if (bptr != buff && isblank(master_text[tlen])) {
+ /*
+ * We can't handle unescaped white space in map names
+ * so just eat the white space. We always have the
+ * "multi" at the beginning of the string so the while
+ * will not fall off the end.
+ */
+ while (isblank(master_text[tlen - 1]))
+ tlen--;
+ strncat(buff, master_text, tlen);
+ bptr += tlen;
+ yyless(tlen);
+ } else {
+ strcpy(master_lval.strtype, master_text);
+ return(MULTITYPE);
+ }
+ }
+
+ {MTYPE} |
+ {MTYPE}/{DNSERVERSTR}{DNATTRSTR}= |
+ {MTYPE}/{DNATTRSTR}= {
+ tlen = master_leng - 1;
+ if (bptr != buff && isblank(master_text[tlen])) {
+ /*
+ * We can't handle unescaped white space in map names
+ * so just eat the white space. We always have the
+ * maptype keyword at the beginning of the string so
+ * the while will not fall off the end.
+ */
+ while (isblank(master_text[tlen - 1]))
+ tlen--;
+ strncat(buff, master_text, tlen);
+ bptr += tlen;
+ yyless(tlen);
+ } else {
+ strcpy(master_lval.strtype, master_text);
+ return(MAPTYPE);
+ }
+ }
+
+ {MULTISEP} { return(DDASH); }
+
+ ":" { return(COLON); }
+
+ "-hosts" {
+ BEGIN(OPTSTR);
+ strcpy(master_lval.strtype, master_text);
+ return MAPHOSTS;
+ }
+
+ "-null" {
+ BEGIN(OPTSTR);
+ strcpy(master_lval.strtype, master_text);
+ return MAPNULL;
+ }
+
+ "-xfn" {
+ /*
+ * The X/Open Federated Naming service isn't supported
+ * and the parser will call YYABORT() when it sees the
+ * MAPXFN token so we must set the start state to the
+ * INITIAL state here for the next yylex() call.
+ */
+ BEGIN(INITIAL);
+ strcpy(master_lval.strtype, master_text);
+ return MAPXFN;
+ }
+
+ "//" {
+ BEGIN(DNSTR);
+ yyless(0);
+ }
+
+ {DNSERVERSTR}{DNATTRSTR}= {
+ BEGIN(DNSTR);
+ yyless(0);
+ }
+
+ {DNATTRSTR}= {
+ BEGIN(DNSTR);
+ yyless(0);
+ }
+
+ {OPTWS}/{NL} {
+ BEGIN(INITIAL);
+ *bptr = '\0';
+ strcpy(master_lval.strtype, buff);
+ bptr = buff;
+ return(MAPNAME);
+ }
+
+ \\. { *bptr++ = *(master_text + 1); }
+
+ {WS} {
+ BEGIN(OPTSTR);
+ *bptr = '\0';
+ strcpy(master_lval.strtype, buff);
+ bptr = buff;
+ return(MAPNAME);
+ }
+
+ {NL} |
+ \x00 {
+ BEGIN(INITIAL);
+ *bptr = '\0';
+ strcpy(master_lval.strtype, buff);
+ return(MAPNAME);
+ }
+
+ <<EOF>> {
+ BEGIN(INITIAL);
+ *bptr = '\0';
+ strcpy(master_lval.strtype, buff);
+ return(MAPNAME);
+ }
+
+ . { *bptr++ = *master_text; }
+}
+
+<DNSTR>{
+ {OPTWS}\\\n{OPTWS} {}
+
+ {DNSERVERSTR} {
+ strcpy(master_lval.strtype, master_text);
+ return DNSERVER;
+ }
+
+ {DNATTRSTR}/"=" {
+ strcpy(master_lval.strtype, master_text);
+ return DNATTR;
+ }
+
+ "=" {
+ return EQUAL;
+ }
+
+ {DNNAMESTR1}/","{DNATTRSTR}"=" {
+ strcpy(master_lval.strtype, master_text);
+ return DNNAME;
+ }
+
+ {DNNAMESTR2} {
+ strcpy(master_lval.strtype, master_text);
+ return DNNAME;
+ }
+
+ {OPTWS}","{OPTWS} {
+ return COMMA;
+ }
+
+ {WS}"=" |
+ "="{WS} {
+ BEGIN(INITIAL);
+ strcpy(master_lval.strtype, master_text);
+ return SPACE;
+ }
+
+ {WS} { BEGIN(OPTSTR); }
+
+ {NL} |
+ \x00 { BEGIN(INITIAL); }
+
+ <<EOF>> { BEGIN(INITIAL); }
+}
+
+<OPTSTR>{
+ {OPTWS}\\\n{OPTWS} {}
+
+ {MULTISEP} {
+ BEGIN(MAPSTR);
+ return(DDASH);
+ }
+
+ {OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); }
+
+ {OPTNTOUT}/{NUMBER} { return(OPT_NTIMEOUT); }
+
+ {NUMBER} {
+ master_lval.longtype = atol(master_text);
+ return(NUMBER);
+ }
+
+ -?symlink { return(OPT_SYMLINK); }
+ -?nobind { return(OPT_NOBIND); }
+ -?nobrowse { return(OPT_NOGHOST); }
+ -?shared { return(OPT_SHARED); }
+ -?slave { return(OPT_SLAVE); }
+ -?private { return(OPT_PRIVATE); }
+ -?strictexpire { return(OPT_STRICTEXPIRE); }
+ -g|--ghost|-?browse { return(OPT_GHOST); }
+ -v|--verbose { return(OPT_VERBOSE); }
+ -d|--debug { return(OPT_DEBUG); }
+ -w|--use-weight-only { return(OPT_USE_WEIGHT); }
+ -r|--random-multimount-selection { return(OPT_RANDOM); }
+
+ {MODE}/{OCTALNUMBER} {
+ BEGIN(OCTAL);
+ return(OPT_MODE);
+ }
+
+ {OPTWS}","{OPTWS} { return(COMMA); }
+
+ {OPTWS} {}
+
+ {SLASHIFYSTR} {
+ strcpy(master_lval.strtype, master_text);
+ return(OPTION);
+ }
+
+ {MACROSTR} {
+ strcpy(master_lval.strtype, master_text);
+ return(OPTION);
+ }
+
+ {OPTIONSTR} {
+ strcpy(master_lval.strtype, master_text);
+ return(OPTION);
+ }
+
+ "=" {
+ strcpy(master_lval.strtype, master_text);
+ return(EQUAL);
+ }
+
+ {WS} {}
+ {NL} |
+ \x00 { BEGIN(INITIAL); }
+
+ <<EOF>> { BEGIN(INITIAL); }
+}
+
+<OCTAL>{
+ {OCTALNUMBER} {
+ master_lval.longtype = strtoul(master_text, NULL, 8);
+ return(OCTALNUMBER);
+ }
+
+ . { BEGIN(OPTSTR); yyless(0); }
+}
+
+%%
+
+#include "automount.h"
+
+int master_wrap(void)
+{
+ return 1;
+}
+
+static void master_echo(void)
+{
+ logmsg("%s", master_text);
+ return;
+}
+
+#ifdef FLEX_SCANNER
+
+void master_set_scan_buffer(const char *buffer)
+{
+ memset(buff, 0, sizeof(buff));
+ optr = buff;
+
+ YY_FLUSH_BUFFER;
+
+ line = buffer;
+ line_pos = &line[0];
+ /*
+ * Ensure buffer is 1 greater than string and is zeroed before
+ * the parse so we can fit the extra NULL which allows us to
+ * explicitly match an end of line within the buffer (ie. the
+ * need for 2 NULLS when parsing in memeory buffers).
+ */
+ line_lim = line + strlen(buffer) + 1;
+}
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+int my_yyinput(char *buffer, int max_size)
+{
+ int n = min(max_size, line_lim - line_pos);
+
+ if (n > 0) {
+ memcpy(buffer, line_pos, n);
+ line_pos += n;
+ }
+ return n;
+}
+
+#else
+
+void master_set_scan_buffer(const char *buffer)
+{
+ line = buffer;
+}
+
+#endif
--- autofs-5.1.4.orig/lib/Makefile
+++ autofs-5.1.4/lib/Makefile
@@ -6,17 +6,14 @@
include ../Makefile.rules
SRCS = cache.c cat_path.c rpc_subs.c mounts.c log.c nsswitch.c \
- master_tok.l master_parse.y nss_tok.c nss_parse.tab.c \
- args.c alarm.c macros.c master.c defaults.c parse_subs.c \
- dev-ioctl-lib.c
+ nss_tok.c nss_parse.tab.c args.c alarm.c macros.c defaults.c \
+ parse_subs.c dev-ioctl-lib.c
RPCS = mount.h mount_clnt.c mount_xdr.c
OBJS = cache.o mount_clnt.o mount_xdr.o cat_path.o rpc_subs.o \
- mounts.o log.o nsswitch.o master_tok.o master_parse.tab.o \
- nss_tok.o nss_parse.tab.o args.o alarm.o macros.o master.o \
- defaults.o parse_subs.o dev-ioctl-lib.o
+ mounts.o log.o nsswitch.o nss_tok.o nss_parse.tab.o args.o \
+ alarm.o macros.o defaults.o parse_subs.o dev-ioctl-lib.o
-YACCSRC = nss_tok.c nss_parse.tab.c nss_parse.tab.h \
- master_tok.c master_parse.tab.c master_parse.tab.h
+YACCSRC = nss_tok.c nss_parse.tab.c nss_parse.tab.h
LIB = autofs.a
@@ -54,16 +51,6 @@ mount_xdr.o: mount_xdr.c
$(CC) $(CFLAGS) -Wno-unused-variable -o mount_xdr.o -c mount_xdr.c
$(STRIP) mount_xdr.o
-master_tok.c: master_tok.l
- $(LEX) -o$@ -Pmaster_ $?
-
-master_parse.tab.c master_parse.tab.h: master_parse.y
- $(YACC) -v -d -p master_ -b master_parse $?
-
-master_tok.o: master_tok.c master_parse.tab.h
-
-master_parse.tab.o: master_parse.tab.c master_parse.tab.h
-
nss_tok.c: nss_tok.l
$(LEX) -o$@ -Pnss_ $?
--- autofs-5.1.4.orig/lib/master.c
+++ /dev/null
@@ -1,1885 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * master.c - master map utility routines.
- *
- * Copyright 2006 Ian Kent <raven@themaw.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
- * USA; either version 2 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * ----------------------------------------------------------------------- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <memory.h>
-#include <limits.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include "automount.h"
-
-/* The root of the map entry tree */
-struct master *master_list = NULL;
-
-extern const char *global_options;
-extern long global_negative_timeout;
-
-/* Attribute to create a joinable thread */
-extern pthread_attr_t th_attr;
-
-extern struct startup_cond suc;
-
-static struct map_source *
-__master_find_map_source(struct master_mapent *,
- const char *, const char *, int, const char **);
-
-static pthread_mutex_t master_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-void master_mutex_lock(void)
-{
- int status = pthread_mutex_lock(&master_mutex);
- if (status)
- fatal(status);
-}
-
-void master_mutex_unlock(void)
-{
- int status = pthread_mutex_unlock(&master_mutex);
- if (status)
- fatal(status);
-}
-
-void master_mutex_lock_cleanup(void *arg)
-{
- master_mutex_unlock();
- return;
-}
-
-int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
- unsigned nobind, unsigned ghost, int submount)
-{
- struct autofs_point *ap;
- int status;
-
- ap = malloc(sizeof(struct autofs_point));
- if (!ap)
- return 0;
-
- ap->state = ST_INIT;
-
- ap->state_pipe[0] = -1;
- ap->state_pipe[1] = -1;
- ap->logpri_fifo = -1;
-
- ap->path = strdup(entry->path);
- if (!ap->path) {
- free(ap);
- return 0;
- }
- ap->pref = NULL;
-
- ap->entry = entry;
- ap->exp_thread = 0;
- ap->readmap_thread = 0;
- /*
- * Program command line option overrides config.
- * We can't use 0 negative timeout so use default.
- */
- if (global_negative_timeout <= 0)
- ap->negative_timeout = defaults_get_negative_timeout();
- else
- ap->negative_timeout = global_negative_timeout;
- ap->exp_timeout = defaults_get_timeout();
- ap->exp_runfreq = 0;
- ap->flags = 0;
-
- if (defaults_get_use_ignore_mount_option())
- ap->flags = MOUNT_FLAG_IGNORE;
- if (ghost)
- ap->flags |= MOUNT_FLAG_GHOST;
-
- if (nobind)
- ap->flags |= MOUNT_FLAG_NOBIND;
-
- if (ap->path[1] == '-')
- ap->type = LKP_DIRECT;
- else
- ap->type = LKP_INDIRECT;
-
- ap->logopt = logopt;
-
- ap->parent = NULL;
- ap->thid = 0;
- ap->submnt_count = 0;
- ap->submount = submount;
- INIT_LIST_HEAD(&ap->mounts);
- INIT_LIST_HEAD(&ap->submounts);
- INIT_LIST_HEAD(&ap->amdmounts);
- ap->shutdown = 0;
-
- status = pthread_mutex_init(&ap->mounts_mutex, NULL);
- if (status) {
- free(ap->path);
- free(ap);
- return 0;
- }
- ap->mode = 0;
-
- entry->ap = ap;
-
- return 1;
-}
-
-void master_free_autofs_point(struct autofs_point *ap)
-{
- struct list_head *p, *head;
- int status;
-
- if (!ap)
- return;
-
- mounts_mutex_lock(ap);
- head = &ap->amdmounts;
- p = head->next;
- while (p != head) {
- struct mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
- p = p->next;
- ext_mount_remove(mnt->ext_mp);
- mnts_remove_amdmount(mnt->mp);
- }
- mounts_mutex_unlock(ap);
-
- status = pthread_mutex_destroy(&ap->mounts_mutex);
- if (status)
- fatal(status);
-
- if (ap->pref)
- free(ap->pref);
- free(ap->path);
- free(ap);
-}
-
-struct map_source *
-master_add_map_source(struct master_mapent *entry,
- char *type, char *format, time_t age,
- int argc, const char **argv)
-{
- struct map_source *source;
- char *ntype, *nformat;
- const char **tmpargv;
-
- source = malloc(sizeof(struct map_source));
- if (!source)
- return NULL;
- memset(source, 0, sizeof(struct map_source));
- source->ref = 1;
-
- if (type) {
- ntype = strdup(type);
- if (!ntype) {
- master_free_map_source(source, 0);
- return NULL;
- }
- source->type = ntype;
- }
-
- if (format) {
- nformat = strdup(format);
- if (!nformat) {
- master_free_map_source(source, 0);
- return NULL;
- }
- source->format = nformat;
- if (!strcmp(nformat, "amd"))
- source->flags |= MAP_FLAG_FORMAT_AMD;
- }
-
- source->age = age;
- source->stale = 1;
-
- tmpargv = copy_argv(argc, argv);
- if (!tmpargv) {
- master_free_map_source(source, 0);
- return NULL;
- }
- source->argc = argc;
- source->argv = tmpargv;
- if (source->argv[0])
- source->name = strdup(source->argv[0]);
-
- master_source_writelock(entry);
-
- if (!entry->maps) {
- source->mc = cache_init(entry->ap, source);
- if (!source->mc) {
- master_free_map_source(source, 0);
- master_source_unlock(entry);
- return NULL;
- }
- entry->maps = source;
- } else {
- struct map_source *this, *last, *next;
-
- /* Typically there only a few map sources */
-
- this = __master_find_map_source(entry, type, format, argc, tmpargv);
- if (this) {
- debug(entry->ap->logopt,
- "map source used without taking reference");
- this->age = age;
- master_free_map_source(source, 0);
- master_source_unlock(entry);
- return this;
- }
-
- source->mc = cache_init(entry->ap, source);
- if (!source->mc) {
- master_free_map_source(source, 0);
- master_source_unlock(entry);
- return NULL;
- }
-
- last = NULL;
- next = entry->maps;
- while (next) {
- last = next;
- next = next->next;
- }
- if (last)
- last->next = source;
- else
- entry->maps = source;
- }
-
- master_source_unlock(entry);
-
- return source;
-}
-
-static int compare_source_type_and_format(struct map_source *map, const char *type, const char *format)
-{
- int res = 0;
-
- if (type) {
- if (!map->type)
- goto done;
-
- if (strcmp(map->type, type))
- goto done;
- } else if (map->type)
- goto done;
-
- if (format) {
- if (!map->format)
- goto done;
-
- if (strcmp(map->format, format))
- goto done;
- } else if (map->format)
- goto done;
-
- res = 1;
-done:
- return res;
-}
-
-static struct map_source *
-__master_find_map_source(struct master_mapent *entry,
- const char *type, const char *format,
- int argc, const char **argv)
-{
- struct map_source *map;
- struct map_source *source = NULL;
- int res;
-
- map = entry->maps;
- while (map) {
- res = compare_source_type_and_format(map, type, format);
- if (!res)
- goto next;
-
- res = compare_argv(map->argc, map->argv, argc, argv);
- if (!res)
- goto next;
-
- source = map;
- break;
-next:
- map = map->next;
- }
-
- return source;
-}
-
-struct map_source *master_find_map_source(struct master_mapent *entry,
- const char *type, const char *format,
- int argc, const char **argv)
-{
- struct map_source *source = NULL;
-
- master_source_readlock(entry);
- source = __master_find_map_source(entry, type, format, argc, argv);
- master_source_unlock(entry);
-
- return source;
-}
-
-struct map_source *
-master_get_map_source(struct master_mapent *entry,
- const char *type, const char *format,
- int argc, const char **argv)
-{
- struct map_source *source = NULL;
-
- master_source_readlock(entry);
- source = __master_find_map_source(entry, type, format, argc, argv);
- if (source)
- source->ref++;
- master_source_unlock(entry);
-
- return source;
-}
-
-static void __master_free_map_source(struct map_source *source, unsigned int free_cache)
-{
- /* instance map sources are not ref counted */
- if (source->ref && --source->ref)
- return;
- if (source->type)
- free(source->type);
- if (source->format)
- free(source->format);
- if (source->name)
- free(source->name);
- if (free_cache && source->mc)
- cache_release(source);
- if (source->lookup) {
- struct map_source *instance;
-
- instance = source->instance;
- while (instance) {
- if (instance->lookup)
- close_lookup(instance->lookup);
- instance = instance->next;
- }
- close_lookup(source->lookup);
- }
- if (source->argv)
- free_argv(source->argc, source->argv);
- if (source->instance) {
- struct map_source *instance, *next;
-
- instance = source->instance;
- while (instance) {
- next = instance->next;
- __master_free_map_source(instance, 0);
- instance = next;
- }
- }
-
- free(source);
-
- return;
-}
-
-void master_free_map_source(struct map_source *source, unsigned int free_cache)
-{
- int status;
-
- status = pthread_mutex_lock(&instance_mutex);
- if (status)
- fatal(status);
-
- __master_free_map_source(source, free_cache);
-
- status = pthread_mutex_unlock(&instance_mutex);
- if (status)
- fatal(status);
-}
-
-struct map_source *master_find_source_instance(struct map_source *source, const char *type, const char *format, int argc, const char **argv)
-{
- struct map_source *map;
- struct map_source *instance = NULL;
- int status, res;
-
- status = pthread_mutex_lock(&instance_mutex);
- if (status)
- fatal(status);
-
- map = source->instance;
- while (map) {
- res = compare_source_type_and_format(map, type, format);
- if (!res)
- goto next;
-
- if (!argv) {
- instance = map;
- break;
- }
-
- res = compare_argv(map->argc, map->argv, argc, argv);
- if (!res)
- goto next;
-
- instance = map;
- break;
-next:
- map = map->next;
- }
-
- status = pthread_mutex_unlock(&instance_mutex);
- if (status)
- fatal(status);
-
- return instance;
-}
-
-struct map_source *
-master_add_source_instance(struct map_source *source, const char *type, const char *format, time_t age, int argc, const char **argv)
-{
- struct map_source *instance;
- struct map_source *new;
- char *ntype, *nformat;
- const char **tmpargv;
- int status;
-
- instance = master_find_source_instance(source, type, format, argc, argv);
- if (instance)
- return instance;
-
- new = malloc(sizeof(struct map_source));
- if (!new)
- return NULL;
- memset(new, 0, sizeof(struct map_source));
-
- if (type) {
- ntype = strdup(type);
- if (!ntype) {
- master_free_map_source(new, 0);
- return NULL;
- }
- new->type = ntype;
- }
-
- if (format) {
- nformat = strdup(format);
- if (!nformat) {
- master_free_map_source(new, 0);
- return NULL;
- }
- new->format = nformat;
- if (!strcmp(nformat, "amd"))
- new->flags |= MAP_FLAG_FORMAT_AMD;
- }
-
- new->age = age;
- new->master_line = 0;
- new->mc = source->mc;
- new->exp_timeout = source->exp_timeout;
- new->stale = 1;
-
- tmpargv = copy_argv(argc, argv);
- if (!tmpargv) {
- master_free_map_source(new, 0);
- return NULL;
- }
- new->argc = argc;
- new->argv = tmpargv;
- if (source->name)
- new->name = strdup(source->name);
-
- status = pthread_mutex_lock(&instance_mutex);
- if (status)
- fatal(status);
-
- if (!source->instance)
- source->instance = new;
- else {
- /*
- * We know there's no other instance of this
- * type so just add to head of list
- */
- new->next = source->instance;
- source->instance = new;
- }
-
- status = pthread_mutex_unlock(&instance_mutex);
- if (status)
- fatal(status);
-
- return new;
-}
-
-int check_stale_instances(struct map_source *source)
-{
- struct map_source *map;
-
- if (!source)
- return 0;
-
- map = source->instance;
- while (map) {
- if (map->stale)
- return 1;
- if (check_stale_instances(map))
- return 1;
- map = map->next;
- }
-
- return 0;
-}
-
-void clear_stale_instances(struct map_source *source)
-{
- struct map_source *map;
-
- if (!source)
- return;
-
- map = source->instance;
- while (map) {
- clear_stale_instances(map);
- if (map->stale)
- map->stale = 0;
- map = map->next;
- }
-
- return;
-}
-
-void send_map_update_request(struct autofs_point *ap)
-{
- struct map_source *map;
- int status, need_update = 0;
-
- status = pthread_mutex_lock(&instance_mutex);
- if (status)
- fatal(status);
-
- map = ap->entry->maps;
- while (map) {
- if (check_stale_instances(map))
- map->stale = 1;
- if (map->stale) {
- need_update = 1;
- break;
- }
- map = map->next;
- }
-
- status = pthread_mutex_unlock(&instance_mutex);
- if (status)
- fatal(status);
-
- if (!need_update)
- return;
-
- st_add_task(ap, ST_READMAP);
-
- return;
-}
-
-void master_source_writelock(struct master_mapent *entry)
-{
- int status;
-
- status = pthread_rwlock_wrlock(&entry->source_lock);
- if (status) {
- logmsg("master_mapent source write lock failed");
- fatal(status);
- }
- return;
-}
-
-void master_source_readlock(struct master_mapent *entry)
-{
- int retries = 25;
- int status;
-
- while (retries--) {
- status = pthread_rwlock_rdlock(&entry->source_lock);
- if (status != EAGAIN && status != EBUSY)
- break;
- else {
- struct timespec t = { 0, 200000000 };
- struct timespec r;
-
- if (status == EAGAIN)
- logmsg("master_mapent source too many readers");
- else
- logmsg("master_mapent source write lock held");
-
- while (nanosleep(&t, &r) == -1 && errno == EINTR)
- memcpy(&t, &r, sizeof(struct timespec));
- }
- }
-
- if (status) {
- logmsg("master_mapent source read lock failed");
- fatal(status);
- }
-
- return;
-}
-
-void master_source_unlock(struct master_mapent *entry)
-{
- int status;
-
- status = pthread_rwlock_unlock(&entry->source_lock);
- if (status) {
- logmsg("master_mapent source unlock failed");
- fatal(status);
- }
- return;
-}
-
-void master_source_lock_cleanup(void *arg)
-{
- struct master_mapent *entry = (struct master_mapent *) arg;
-
- master_source_unlock(entry);
-
- return;
-}
-
-void master_source_current_wait(struct master_mapent *entry)
-{
- int status;
-
- status = pthread_mutex_lock(&entry->current_mutex);
- if (status) {
- logmsg("entry current source lock failed");
- fatal(status);
- }
-
- while (entry->current != NULL) {
- status = pthread_cond_wait(
- &entry->current_cond, &entry->current_mutex);
- if (status) {
- logmsg("entry current source condition wait failed");
- fatal(status);
- }
- }
-
- return;
-}
-
-void master_source_current_signal(struct master_mapent *entry)
-{
- int status;
-
- status = pthread_cond_signal(&entry->current_cond);
- if (status) {
- logmsg("entry current source condition signal failed");
- fatal(status);
- }
-
- status = pthread_mutex_unlock(&entry->current_mutex);
- if (status) {
- logmsg("entry current source unlock failed");
- fatal(status);
- }
-
- return;
-}
-
-struct master_mapent *master_find_mapent(struct master *master, const char *path)
-{
- struct list_head *head, *p;
-
- head = &master->mounts;
- list_for_each(p, head) {
- struct master_mapent *entry;
-
- entry = list_entry(p, struct master_mapent, list);
-
- if (!strcmp(entry->path, path))
- return entry;
- }
-
- return NULL;
-}
-
-unsigned int master_partial_match_mapent(struct master *master, const char *path)
-{
- struct list_head *head, *p;
- size_t path_len = strlen(path);
- int ret = 0;
-
- head = &master->mounts;
- list_for_each(p, head) {
- struct master_mapent *entry;
- size_t entry_len;
- size_t cmp_len;
-
- entry = list_entry(p, struct master_mapent, list);
-
- entry_len = strlen(entry->path);
- cmp_len = min(entry_len, path_len);
-
- if (!strncmp(entry->path, path, cmp_len)) {
- /* paths are equal, matching master map entry ? */
- if (entry_len == path_len) {
- if (entry->maps &&
- entry->maps->flags & MAP_FLAG_FORMAT_AMD)
- ret = 1;
- else
- ret = -1;
- break;
- }
-
- /* amd mount conflicts with entry mount */
- if (entry_len > path_len &&
- *(entry->path + path_len) == '/') {
- ret = -1;
- break;
- }
-
- /* entry mount conflicts with amd mount */
- if (entry_len < path_len &&
- *(path + entry_len) == '/') {
- ret = -1;
- break;
- }
- }
- }
-
- return ret;
-}
-
-struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
-{
- struct master_mapent *entry;
- int status;
- char *tmp;
-
- entry = malloc(sizeof(struct master_mapent));
- if (!entry)
- return NULL;
-
- memset(entry, 0, sizeof(struct master_mapent));
-
- tmp = strdup(path);
- if (!tmp) {
- free(entry);
- return NULL;
- }
- entry->path = tmp;
-
- entry->thid = 0;
- entry->age = age;
- entry->master = master;
- entry->current = NULL;
- entry->maps = NULL;
- entry->ap = NULL;
-
- status = pthread_rwlock_init(&entry->source_lock, NULL);
- if (status)
- fatal(status);
-
- status = pthread_mutex_init(&entry->current_mutex, NULL);
- if (status)
- fatal(status);
-
- status = pthread_cond_init(&entry->current_cond, NULL);
- if (status)
- fatal(status);
-
- INIT_LIST_HEAD(&entry->list);
-
- return entry;
-}
-
-void master_add_mapent(struct master *master, struct master_mapent *entry)
-{
- list_add_tail(&entry->list, &master->mounts);
- return;
-}
-
-void master_remove_mapent(struct master_mapent *entry)
-{
- struct master *master = entry->master;
-
- if (entry->ap->submount)
- return;
-
- if (!list_empty(&entry->list)) {
- list_del_init(&entry->list);
- list_add(&entry->join, &master->completed);
- }
-
- return;
-}
-
-void master_free_mapent_sources(struct master_mapent *entry, unsigned int free_cache)
-{
- if (entry->maps) {
- struct map_source *m, *n;
-
- m = entry->maps;
- while (m) {
- n = m->next;
- master_free_map_source(m, free_cache);
- m = n;
- }
- entry->maps = NULL;
- }
-
- return;
-}
-
-void master_free_mapent(struct master_mapent *entry)
-{
- int status;
-
- if (entry->path)
- free(entry->path);
-
- master_free_autofs_point(entry->ap);
-
- status = pthread_rwlock_destroy(&entry->source_lock);
- if (status)
- fatal(status);
-
- status = pthread_mutex_destroy(&entry->current_mutex);
- if (status)
- fatal(status);
-
- status = pthread_cond_destroy(&entry->current_cond);
- if (status)
- fatal(status);
-
- free(entry);
-
- return;
-}
-
-struct master *master_new(const char *name, unsigned int timeout, unsigned int flags)
-{
- struct master *master;
- char *tmp;
-
- master = malloc(sizeof(struct master));
- if (!master)
- return NULL;
-
- if (!name)
- tmp = (char *) defaults_get_master_map();
- else
- tmp = strdup(name);
-
- if (!tmp) {
- free(master);
- return NULL;
- }
-
- master->name = tmp;
- master->nc = NULL;
-
- master->recurse = 0;
- master->depth = 0;
- master->reading = 0;
- master->read_fail = 0;
- master->readall = 0;
- master->default_ghost = flags & DAEMON_FLAGS_GHOST;
- master->default_timeout = timeout;
- master->default_logging = defaults_get_logging();
- master->logopt = master->default_logging;
-
- INIT_LIST_HEAD(&master->mounts);
- INIT_LIST_HEAD(&master->completed);
-
- return master;
-}
-
-static void master_add_amd_mount_section_mounts(struct master *master, time_t age)
-{
- unsigned int m_logopt = master->logopt;
- struct master_mapent *entry;
- struct map_source *source;
- unsigned int loglevel;
- unsigned int logopt;
- unsigned int flags;
- char *argv[2];
- char **paths;
- int ret;
- int i;
-
- loglevel = conf_amd_get_log_options();
-
- paths = conf_amd_get_mount_paths();
- if (!paths)
- return;
-
- i = 0;
- while (paths[i]) {
- const char *path = paths[i];
- unsigned int ghost = 0;
- time_t timeout;
- char *type = NULL;
- char *map = NULL;
- char *opts;
-
- ret = master_partial_match_mapent(master, path);
- if (ret) {
- /* If this amd entry is already present in the
- * master map it's not a duplicate, don't issue
- * an error message.
- */
- if (ret == 1)
- goto next;
- info(m_logopt,
- "amd section mount path conflict, %s ignored",
- path);
- goto next;
- }
-
- map = conf_amd_get_map_name(path);
- if (!map) {
- error(m_logopt,
- "failed to get map name for amd section mount %s",
- path);
- goto next;
- }
-
- entry = master_new_mapent(master, path, age);
- if (!entry) {
- error(m_logopt,
- "failed to allocate new amd section mount %s",
- path);
- goto next;
- }
-
- logopt = m_logopt;
- if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
- logopt = LOGOPT_DEBUG;
- else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
- logopt = LOGOPT_VERBOSE;
-
- /* It isn't possible to provide the fullybrowsable amd
- * browsing functionality within the autofs framework.
- * This flag will not be set if browsable_dirs = full
- * in the configuration or fullybrowsable is present as
- * an option.
- */
- flags = conf_amd_get_flags(path);
- if (flags & CONF_BROWSABLE_DIRS)
- ghost = 1;
-
- ret = master_add_autofs_point(entry, logopt, 0, ghost, 0);
- if (!ret) {
- error(m_logopt, "failed to add autofs_point");
- master_free_mapent(entry);
- goto next;
- }
-
- opts = conf_amd_get_map_options(path);
- if (opts) {
- /* autofs uses the equivalent of cache:=inc,sync
- * (except for file maps which use cache:=all,sync)
- * but if the map is large then it may be necessary
- * to read the whole map at startup even if browsing
- * is is not enabled, so look for cache:=all in the
- * map_options configuration entry.
- */
- if (strstr(opts, "cache:=all"))
- entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
- free(opts);
- }
-
- type = conf_amd_get_map_type(path);
- argv[0] = map;
- argv[1] = NULL;
-
- source = master_add_map_source(entry, type, "amd",
- age, 1, (const char **) argv);
- if (!source) {
- error(m_logopt,
- "failed to add source for amd section mount %s",
- path);
- master_free_mapent(entry);
- goto next;
- }
-
- timeout = conf_amd_get_dismount_interval(path);
- set_exp_timeout(entry->ap, source, timeout);
- source->master_line = 0;
-
- entry->age = age;
- entry->current = NULL;
-
- master_add_mapent(master, entry);
-next:
- if (type)
- free(type);
- if (map)
- free(map);
- i++;
- }
-
- i = 0;
- while (paths[i])
- free(paths[i++]);
- free(paths);
-}
-
-static void wait_for_lookups_and_lock(struct master *master)
-{
- struct list_head *p, *head;
- int status;
-
-again:
- master_mutex_lock();
-
- head = &master->mounts;
- p = head->next;
- while (p != head) {
- struct master_mapent *this;
-
- this = list_entry(p, struct master_mapent, list);
-
- status = pthread_rwlock_trywrlock(&this->source_lock);
- if (status) {
- struct timespec t = { 0, 200000000 };
- struct timespec r;
-
- master_mutex_unlock();
-
- while (nanosleep(&t, &r) == -1 && errno == EINTR)
- memcpy(&t, &r, sizeof(struct timespec));
-
- goto again;
- }
- master_source_unlock(this);
-
- p = p->next;
- }
-}
-
-int master_read_master(struct master *master, time_t age)
-{
- unsigned int logopt = master->logopt;
- struct mapent_cache *nc;
-
- /*
- * We need to clear and re-populate the null map entry cache
- * before alowing anyone else to use it.
- */
- wait_for_lookups_and_lock(master);
- if (master->nc) {
- cache_writelock(master->nc);
- nc = master->nc;
- cache_clean_null_cache(nc);
- } else {
- nc = cache_init_null_cache(master);
- if (!nc) {
- error(logopt,
- "failed to init null map cache for %s",
- master->name);
- return 0;
- }
- cache_writelock(nc);
- master->nc = nc;
- }
- master_init_scan();
- lookup_nss_read_master(master, age);
- cache_unlock(nc);
- master_add_amd_mount_section_mounts(master, age);
-
- if (!master->read_fail)
- master_mount_mounts(master, age);
- else {
- master->read_fail = 0;
- /* HUP signal sets master->readall == 1 only */
- if (!master->readall) {
- master_mutex_unlock();
- return 0;
- } else
- master_mount_mounts(master, age);
- }
-
- if (list_empty(&master->mounts))
- warn(logopt, "no mounts in table");
-
- master_mutex_unlock();
-
- return 1;
-}
-
-int master_submount_list_empty(struct autofs_point *ap)
-{
- int res = 0;
-
- mounts_mutex_lock(ap);
- if (list_empty(&ap->submounts))
- res = 1;
- mounts_mutex_unlock(ap);
-
- return res;
-}
-
-int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
-{
- struct mnt_list *this, *sbmnt;
- int ret = 1;
-
- this = mnts_find_submount(path);
- if (this) {
- /* We have found a submount to expire */
- st_mutex_lock();
-
- if (this->ap->state == ST_SHUTDOWN) {
- this = NULL;
- st_mutex_unlock();
- goto done;
- }
-
- this->ap->shutdown = ap->shutdown;
-
- __st_add_task(this->ap, state);
-
- st_mutex_unlock();
-
- st_wait_task(this->ap, state, 0);
-
- /*
- * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
- * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
- * to ST_READY.
- */
- st_mutex_lock();
- while ((sbmnt = mnts_find_submount(path))) {
- struct timespec t = { 0, 300000000 };
- struct timespec r;
-
- if (sbmnt->ap->state != ST_SHUTDOWN &&
- sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
- sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
- ret = 0;
- mnts_put_mount(sbmnt);
- break;
- }
- mnts_put_mount(sbmnt);
-
- st_mutex_unlock();
- while (nanosleep(&t, &r) == -1 && errno == EINTR)
- memcpy(&t, &r, sizeof(struct timespec));
- st_mutex_lock();
- }
- st_mutex_unlock();
-done:
- mnts_put_mount(this);
- }
-
- return ret;
-}
-
-void master_notify_state_change(struct master *master, int sig)
-{
- struct master_mapent *entry;
- struct autofs_point *ap;
- struct list_head *p;
- int cur_state;
- unsigned int logopt;
-
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
- master_mutex_lock();
-
- list_for_each(p, &master->mounts) {
- enum states next = ST_INVAL;
-
- entry = list_entry(p, struct master_mapent, list);
-
- ap = entry->ap;
- logopt = ap->logopt;
-
- st_mutex_lock();
-
- if (ap->state == ST_SHUTDOWN)
- goto next;
-
- switch (sig) {
- case SIGTERM:
- case SIGINT:
- if (ap->state != ST_SHUTDOWN_PENDING &&
- ap->state != ST_SHUTDOWN_FORCE) {
- next = ST_SHUTDOWN_PENDING;
- ap->shutdown = 1;
- __st_add_task(ap, next);
- }
- break;
-#ifdef ENABLE_FORCED_SHUTDOWN
- case SIGUSR2:
- if (ap->state != ST_SHUTDOWN_FORCE &&
- ap->state != ST_SHUTDOWN_PENDING) {
- next = ST_SHUTDOWN_FORCE;
- ap->shutdown = 1;
- __st_add_task(ap, next);
- }
- break;
-#endif
- case SIGUSR1:
- assert(ap->state == ST_READY);
- next = ST_PRUNE;
- __st_add_task(ap, next);
- break;
- }
-next:
- if (next != ST_INVAL)
- debug(logopt,
- "sig %d switching %s from %d to %d",
- sig, ap->path, ap->state, next);
-
- st_mutex_unlock();
- }
-
- master_mutex_unlock();
- pthread_setcancelstate(cur_state, NULL);
-
- return;
-}
-
-static int master_do_mount(struct master_mapent *entry)
-{
- struct startup_cond suc;
- struct autofs_point *ap;
- pthread_t thid;
- int status;
-
- ap = entry->ap;
-
- if (handle_mounts_startup_cond_init(&suc)) {
- crit(ap->logopt,
- "failed to init startup cond for mount %s", entry->path);
- return 0;
- }
-
- suc.ap = ap;
- suc.root = ap->path;
- suc.done = 0;
- suc.status = 0;
-
- if (!(do_force_unlink & UNLINK_AND_EXIT))
- debug(ap->logopt, "mounting %s", entry->path);
-
- status = pthread_create(&thid, &th_attr, handle_mounts, &suc);
- if (status) {
- crit(ap->logopt,
- "failed to create mount handler thread for %s",
- entry->path);
- handle_mounts_startup_cond_destroy(&suc);
- return 0;
- }
-
- while (!suc.done) {
- status = pthread_cond_wait(&suc.cond, &suc.mutex);
- if (status)
- fatal(status);
- }
-
- if (suc.status) {
- if (!(do_force_unlink & UNLINK_AND_EXIT))
- error(ap->logopt, "failed to startup mount");
- handle_mounts_startup_cond_destroy(&suc);
- return 0;
- }
- entry->thid = thid;
-
- handle_mounts_startup_cond_destroy(&suc);
-
- return 1;
-}
-
-static void check_update_map_sources(struct master_mapent *entry, int readall)
-{
- struct map_source *source, *last;
- struct autofs_point *ap;
- int map_stale = 0;
-
- if (readall)
- map_stale = 1;
-
- ap = entry->ap;
-
- master_source_writelock(entry);
-
- last = NULL;
- source = entry->maps;
- while (source) {
- if (readall)
- source->stale = 1;
-
- /*
- * If a map source is no longer valid and all it's
- * entries have expired away we can get rid of it.
- */
- if (entry->age > source->age) {
- struct mapent *me;
- cache_readlock(source->mc);
- me = cache_lookup_first(source->mc);
- if (!me) {
- struct map_source *next = source->next;
-
- cache_unlock(source->mc);
-
- if (!last)
- entry->maps = next;
- else
- last->next = next;
-
- if (entry->maps == source)
- entry->maps = next;
-
- master_free_map_source(source, 1);
-
- source = next;
- continue;
- } else {
- source->stale = 1;
- map_stale = 1;
- }
- cache_unlock(source->mc);
- }
- last = source;
- source = source->next;
- }
-
- master_source_unlock(entry);
-
- /* The map sources have changed */
- if (map_stale)
- st_add_task(ap, ST_READMAP);
-
- return;
-}
-
-int master_mount_mounts(struct master *master, time_t age)
-{
- struct mapent_cache *nc = master->nc;
- struct list_head *p, *head;
- int cur_state;
-
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
-
- head = &master->mounts;
- p = head->next;
- while (p != head) {
- struct master_mapent *this;
- struct autofs_point *ap;
- struct mapent *ne, *nested;
- struct stat st;
- int state_pipe, save_errno;
- int ret;
-
- this = list_entry(p, struct master_mapent, list);
- p = p->next;
-
- ap = this->ap;
-
- /* A master map entry has gone away */
- if (this->age < age) {
- st_add_task(ap, ST_SHUTDOWN_PENDING);
- continue;
- }
-
- cache_readlock(nc);
- ne = cache_lookup_distinct(nc, this->path);
- /*
- * If this path matched a nulled entry the master map entry
- * must be an indirect mount so the master map entry line
- * number may be obtained from this->maps.
- */
- if (ne) {
- int lineno = ne->age;
- cache_unlock(nc);
-
- /* null entry appears after map entry */
- if (this->maps->master_line < lineno) {
- warn(ap->logopt,
- "ignoring null entry that appears after "
- "existing entry for %s", this->path);
- goto cont;
- }
- if (ap->state != ST_INIT) {
- st_add_task(ap, ST_SHUTDOWN_PENDING);
- continue;
- }
- /*
- * The map entry hasn't been started yet and we've
- * seen a preceeding null map entry for it so just
- * delete it from the master map entry list so it
- * doesn't get in the road.
- */
- list_del_init(&this->list);
- master_free_mapent_sources(ap->entry, 1);
- master_free_mapent(ap->entry);
- continue;
- }
- nested = cache_partial_match(nc, this->path);
- if (nested) {
- error(ap->logopt,
- "removing invalid nested null entry %s",
- nested->key);
- nested = cache_partial_match(nc, this->path);
- if (nested)
- cache_delete(nc, nested->key);
- }
- cache_unlock(nc);
-cont:
- st_mutex_lock();
-
- state_pipe = this->ap->state_pipe[1];
-
- /* No pipe so mount is needed */
- ret = fstat(state_pipe, &st);
- save_errno = errno;
-
- st_mutex_unlock();
-
- if (!ret)
- check_update_map_sources(this, master->readall);
- else if (ret == -1 && save_errno == EBADF) {
- if (!master_do_mount(this)) {
- list_del_init(&this->list);
- master_free_mapent_sources(ap->entry, 1);
- master_free_mapent(ap->entry);
- }
- }
- }
-
- pthread_setcancelstate(cur_state, NULL);
-
- return 1;
-}
-
-/* The nss source instances end up in reverse order. */
-static void list_source_instances(struct map_source *source, struct map_source *instance)
-{
- if (!source || !instance) {
- printf("none");
- return;
- }
-
- if (instance->next)
- list_source_instances(source, instance->next);
-
- /*
- * For convienience we map nss instance type "files" to "file".
- * Check for that and report corrected instance type.
- */
- if (strcmp(instance->type, "file"))
- printf("%s ", instance->type);
- else {
- if (source->argv && *(source->argv[0]) != '/')
- printf("files ");
- else
- printf("%s ", instance->type);
- }
-
- return;
-}
-
-static void print_map_info(struct map_source *source)
-{
- int argc = source->argc;
- int i, multi, map_num;
-
- multi = (source->type && !strcmp(source->type, "multi"));
- map_num = 1;
- for (i = 0; i < argc; i++) {
- if (source->argv[i] && *source->argv[i] != '-') {
- if (!multi)
- printf(" map: %s\n", source->argv[i]);
- else
- printf(" map[%i]: %s\n", map_num, source->argv[i]);
- i++;
- }
-
- if (i >= argc)
- return;
-
- if (!strcmp(source->argv[i], "--"))
- continue;
-
- if (source->argv[i]) {
- int need_newline = 0;
- int j;
-
- if (!multi)
- printf(" arguments:");
- else
- printf(" arguments[%i]:", map_num);
-
- for (j = i; j < source->argc; j++) {
- if (!strcmp(source->argv[j], "--"))
- break;
- printf(" %s", source->argv[j]);
- i++;
- need_newline = 1;
- }
- if (need_newline)
- printf("\n");
- }
- if (multi)
- map_num++;
- }
-
- return;
-}
-
-static int match_type(const char *source, const char *type)
-{
- if (!strcmp(source, type))
- return 1;
- /* Sources file and files are synonymous */
- if (!strncmp(source, type, 4) && (strlen(source) <= 5))
- return 1;
- return 0;
-}
-
-static char *get_map_name(const char *string)
-{
- char *name, *tmp;
- char *start, *end, *base;
-
- tmp = strdup(string);
- if (!tmp) {
- printf("error: allocation failure: %s\n", strerror(errno));
- return NULL;
- }
-
- base = basename(tmp);
- end = strchr(base, ',');
- if (end)
- *end = '\0';
- start = strchr(tmp, '=');
- if (start)
- start++;
- else {
- char *colon = strrchr(base, ':');
- if (colon)
- start = ++colon;
- else
- start = base;
- }
-
- name = strdup(start);
- if (!name)
- printf("error: allocation failure: %s\n", strerror(errno));
- free(tmp);
-
- return name;
-}
-
-static int match_name(struct map_source *source, const char *name)
-{
- int argc = source->argc;
- int ret = 0;
- int i;
-
- /*
- * This can't work for old style "multi" type sources since
- * there's no way to know from which map the cache entry came
- * from and duplicate entries are ignored at map read time.
- * All we can really do is list all the entries for the given
- * multi map if one of its map names matches.
- */
- for (i = 0; i < argc; i++) {
- if (i == 0 || !strcmp(source->argv[i], "--")) {
- if (i != 0) {
- i++;
- if (i >= argc)
- break;
- }
-
- if (source->argv[i] && *source->argv[i] != '-') {
- char *map = get_map_name(source->argv[i]);
- if (!map)
- break;
- if (!strcmp(map, name)) {
- ret = 1;
- free(map);
- break;
- }
- free(map);
- }
- }
- }
-
- return ret;
-}
-
-int dump_map(struct master *master, const char *type, const char *name)
-{
- struct list_head *p, *head;
-
- if (list_empty(&master->mounts)) {
- printf("no master map entries found\n");
- return 1;
- }
-
- head = &master->mounts;
- p = head->next;
- while (p != head) {
- struct map_source *source;
- struct master_mapent *this;
- struct autofs_point *ap;
- time_t now = monotonic_time(NULL);
-
- this = list_entry(p, struct master_mapent, list);
- p = p->next;
-
- ap = this->ap;
-
- /*
- * Ensure we actually read indirect map entries so we can
- * list them. The map reads won't read any indirect map
- * entries (other than those in a file map) unless the
- * browse option is set.
- */
- if (ap->type == LKP_INDIRECT)
- ap->flags |= MOUNT_FLAG_GHOST;
-
- /* Read the map content into the cache */
- if (lookup_nss_read_map(ap, NULL, now))
- lookup_prune_cache(ap, now);
- else {
- printf("failed to read map\n");
- lookup_close_lookup(ap);
- continue;
- }
-
- if (!this->maps) {
- printf("no map sources found for %s\n", ap->path);
- lookup_close_lookup(ap);
- continue;
- }
-
- source = this->maps;
- while (source) {
- struct map_source *instance;
- struct mapent *me;
-
- instance = NULL;
- if (source->type) {
- if (!match_type(source->type, type)) {
- source = source->next;
- continue;
- }
- if (!match_name(source, name)) {
- source = source->next;
- continue;
- }
- instance = source;
- } else {
- struct map_source *map;
-
- map = source->instance;
- while (map) {
- if (!match_type(map->type, type)) {
- map = map->next;
- continue;
- }
- if (!match_name(map, name)) {
- map = map->next;
- continue;
- }
- instance = map;
- break;
- }
- }
-
- if (!instance) {
- source = source->next;
- lookup_close_lookup(ap);
- continue;
- }
-
- me = cache_lookup_first(source->mc);
- if (!me)
- printf("no keys found in map\n");
- else {
- do {
- if (me->source == instance)
- printf("%s\t%s\n", me->key, me->mapent);
- } while ((me = cache_lookup_next(source->mc, me)));
- }
-
- lookup_close_lookup(ap);
- return 1;
- }
- lookup_close_lookup(ap);
- }
-
- return 0;
-}
-
-int master_show_mounts(struct master *master)
-{
- struct list_head *p, *head;
-
- printf("\nautofs dump map information\n"
- "===========================\n\n");
-
- printf("global options: ");
- if (!global_options)
- printf("none configured\n");
- else {
- printf("%s\n", global_options);
- unsigned int append_options = defaults_get_append_options();
- const char *append = append_options ? "will" : "will not";
- printf("global options %s be appended to map entries\n", append);
- }
-
- if (list_empty(&master->mounts)) {
- printf("no master map entries found\n\n");
- return 1;
- }
-
- head = &master->mounts;
- p = head->next;
- while (p != head) {
- struct map_source *source;
- struct master_mapent *this;
- struct autofs_point *ap;
- time_t now = monotonic_time(NULL);
- unsigned int count = 0;
-
- this = list_entry(p, struct master_mapent, list);
- p = p->next;
-
- ap = this->ap;
-
- printf("\nMount point: %s\n", ap->path);
-
- printf("\nsource(s):\n");
-
- /*
- * Ensure we actually read indirect map entries so we can
- * list them. The map reads won't read any indirect map
- * entries (other than those in a file map) unless the
- * browse option is set.
- */
- if (ap->type == LKP_INDIRECT)
- ap->flags |= MOUNT_FLAG_GHOST;
-
- /* Read the map content into the cache */
- if (lookup_nss_read_map(ap, NULL, now))
- lookup_prune_cache(ap, now);
- else {
- printf(" failed to read map\n\n");
- continue;
- }
-
- if (!this->maps) {
- printf(" no map sources found\n\n");
- continue;
- }
-
- source = this->maps;
- while (source) {
- struct mapent *me;
-
- if (source->type)
- printf("\n type: %s\n", source->type);
- else {
- printf("\n instance type(s): ");
- list_source_instances(source, source->instance);
- printf("\n");
- }
-
- if (source->argc >= 1) {
- print_map_info(source);
- if (count && ap->type == LKP_INDIRECT)
- printf(" duplicate indirect map entry"
- " will be ignored at run time\n");
- }
-
- printf("\n");
-
- me = cache_lookup_first(source->mc);
- if (!me)
- printf(" no keys found in map\n");
- else {
- do {
- printf(" %s | %s\n", me->key, me->mapent);
- } while ((me = cache_lookup_next(source->mc, me)));
- }
-
- count++;
-
- source = source->next;
- }
-
- lookup_close_lookup(ap);
-
- printf("\n");
- }
-
- return 1;
-}
-
-int master_list_empty(struct master *master)
-{
- int res = 0;
-
- master_mutex_lock();
- if (list_empty(&master->mounts))
- res = 1;
- master_mutex_unlock();
-
- return res;
-}
-
-int master_done(struct master *master)
-{
- struct list_head *head, *p;
- struct master_mapent *entry;
- int res = 0;
-
- head = &master->completed;
- p = head->next;
- while (p != head) {
- entry = list_entry(p, struct master_mapent, join);
- p = p->next;
- list_del(&entry->join);
- pthread_join(entry->thid, NULL);
- master_free_mapent_sources(entry, 1);
- master_free_mapent(entry);
- }
- if (list_empty(&master->mounts))
- res = 1;
-
- return res;
-}
-
-unsigned int master_get_logopt(void)
-{
- return master_list ? master_list->logopt : LOGOPT_NONE;
-}
-
-int master_kill(struct master *master)
-{
- if (!list_empty(&master->mounts))
- return 0;
-
- if (master->name)
- free(master->name);
-
- cache_release_null_cache(master);
- free(master);
-
- return 1;
-}
--- autofs-5.1.4.orig/lib/master_parse.y
+++ /dev/null
@@ -1,983 +0,0 @@
-%{
-/* ----------------------------------------------------------------------- *
- *
- * master_parser.y - master map buffer parser.
- *
- * Copyright 2006 Ian Kent <raven@themaw.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
- * USA; either version 2 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * ----------------------------------------------------------------------- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <sys/ioctl.h>
-
-#include "automount.h"
-#include "master.h"
-
-#define MAX_ERR_LEN 512
-
-extern struct master *master_list;
-
-char **add_argv(int, char **, char *);
-const char **copy_argv(int, const char **);
-int free_argv(int, const char **);
-
-extern FILE *master_in;
-extern char *master_text;
-extern int master_lex(void);
-extern int master_lineno;
-extern void master_set_scan_buffer(const char *);
-
-static char *master_strdup(char *);
-static void local_init_vars(void);
-static void local_free_vars(void);
-static void trim_maptype(char *);
-static int add_multi_mapstr(void);
-
-static int master_error(const char *s);
-static int master_notify(const char *s);
-static int master_msg(const char *s);
-
-static char *path;
-static char *type;
-static char *format;
-static long timeout;
-static long negative_timeout;
-static unsigned symlnk;
-static unsigned strictexpire;
-static unsigned nobind;
-static unsigned ghost;
-extern unsigned global_selection_options;
-static unsigned random_selection;
-static unsigned use_weight;
-static unsigned long mode;
-static char **tmp_argv;
-static int tmp_argc;
-static char **local_argv;
-static int local_argc;
-
-#define PROPAGATION_SHARED MOUNT_FLAG_SHARED
-#define PROPAGATION_SLAVE MOUNT_FLAG_SLAVE
-#define PROPAGATION_PRIVATE MOUNT_FLAG_PRIVATE
-#define PROPAGATION_MASK (MOUNT_FLAG_SHARED | \
- MOUNT_FLAG_SLAVE | \
- MOUNT_FLAG_PRIVATE)
-static unsigned int propagation;
-
-static char errstr[MAX_ERR_LEN];
-
-static unsigned int verbose;
-static unsigned int debug;
-
-static int lineno;
-
-#define YYDEBUG 0
-
-#ifndef YYENABLE_NLS
-#define YYENABLE_NLS 0
-#endif
-#ifndef YYLTYPE_IS_TRIVIAL
-#define YYLTYPE_IS_TRIVIAL 0
-#endif
-
-#if YYDEBUG
-static int master_fprintf(FILE *, char *, ...);
-#undef YYFPRINTF
-#define YYFPRINTF master_fprintf
-#endif
-
-%}
-
-%union {
- char strtype[2048];
- int inttype;
- long longtype;
-}
-
-%token COMMENT
-%token MAP
-%token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOBIND OPT_NOGHOST OPT_GHOST OPT_VERBOSE
-%token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT OPT_SYMLINK OPT_MODE
-%token OPT_STRICTEXPIRE OPT_SHARED OPT_SLAVE OPT_PRIVATE
-%token COLON COMMA NL DDASH
-%type <strtype> map
-%type <strtype> options
-%type <strtype> dn
-%type <strtype> dnattrs
-%type <strtype> dnattr
-%type <strtype> option
-%type <strtype> daemon_option
-%type <strtype> mount_option
-%token <strtype> PATH
-%token <strtype> QUOTE
-%token <strtype> NILL
-%token <strtype> SPACE
-%token <strtype> EQUAL
-%token <strtype> MULTITYPE
-%token <strtype> MAPTYPE
-%token <strtype> DNSERVER
-%token <strtype> DNATTR
-%token <strtype> DNNAME
-%token <strtype> MAPHOSTS
-%token <strtype> MAPNULL
-%token <strtype> MAPXFN
-%token <strtype> MAPNAME
-%token <longtype> NUMBER
-%token <longtype> OCTALNUMBER
-%token <strtype> OPTION
-
-%start file
-
-%%
-
-file: {
- master_lineno = 0;
-#if YYDEBUG != 0
- master_debug = YYDEBUG;
-#endif
- } line
- ;
-
-line:
- | PATH mapspec
- {
- path = master_strdup($1);
- if (!path) {
- local_free_vars();
- YYABORT;
- }
- }
- | PATH MULTITYPE maplist
- {
- char *tmp = NULL;
-
- trim_maptype($2);
-
- if (path)
- free(path);
- path = master_strdup($1);
- if (!path) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
-
- if ((tmp = strchr($2, ',')))
- *tmp++ = '\0';
-#ifndef WITH_HESIOD
- /* Map type or map type parser is hesiod */
- if (!strcmp($2, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
- master_error("hesiod support not built in");
- local_free_vars();
- YYABORT;
- }
-#endif
- if (type)
- free(type);
- type = master_strdup($2);
- if (!type) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- if (tmp) {
- if (format)
- free(format);
- format = master_strdup(tmp);
- if (!format) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- }
- | PATH COLON { master_notify($1); YYABORT; }
- | PATH OPTION { master_notify($2); YYABORT; }
- | PATH NILL { master_notify($2); YYABORT; }
- | PATH OPT_RANDOM { master_notify($1); YYABORT; }
- | PATH OPT_USE_WEIGHT { master_notify($1); YYABORT; }
- | PATH OPT_DEBUG { master_notify($1); YYABORT; }
- | PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
- | PATH OPT_SYMLINK { master_notify($1); YYABORT; }
- | PATH OPT_STRICTEXPIRE { master_notify($1); YYABORT; }
- | PATH OPT_SHARED { master_notify($1); YYABORT; }
- | PATH OPT_SLAVE { master_notify($1); YYABORT; }
- | PATH OPT_PRIVATE { master_notify($1); YYABORT; }
- | PATH OPT_NOBIND { master_notify($1); YYABORT; }
- | PATH OPT_GHOST { master_notify($1); YYABORT; }
- | PATH OPT_NOGHOST { master_notify($1); YYABORT; }
- | PATH OPT_VERBOSE { master_notify($1); YYABORT; }
- | PATH OPT_MODE { master_notify($1); YYABORT; }
- | PATH { master_notify($1); YYABORT; }
- | QUOTE { master_notify($1); YYABORT; }
- | OPTION { master_notify($1); YYABORT; }
- | NILL { master_notify($1); YYABORT; }
- | COMMENT { YYABORT; }
- ;
-
-mapspec: map
- {
- if (local_argv)
- free_argv(local_argc, (const char **) local_argv);
- local_argc = tmp_argc;
- local_argv = tmp_argv;
- tmp_argc = 0;
- tmp_argv = NULL;
- }
- | map options
- {
- if (local_argv)
- free_argv(local_argc, (const char **) local_argv);
- local_argc = tmp_argc;
- local_argv = tmp_argv;
- tmp_argc = 0;
- tmp_argv = NULL;
- }
- ;
-
-maplist: map
- {
- if (!add_multi_mapstr()) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- | map options
- {
- if (!add_multi_mapstr()) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- | maplist DDASH map
- {
- local_argc++;
- local_argv = add_argv(local_argc, local_argv, "--");
- if (!local_argv) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- if (!add_multi_mapstr()) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- | maplist DDASH map options
- {
- local_argc++;
- local_argv = add_argv(local_argc, local_argv, "--");
- if (!local_argv) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- if (!add_multi_mapstr()) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- ;
-
-map: PATH
- {
- tmp_argc++;
- tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
- if (!tmp_argv) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- | MAPNAME
- {
- tmp_argc++;
- tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
- if (!tmp_argv) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- | MAPHOSTS
- {
- if (type)
- free(type);
- type = master_strdup($1 + 1);
- if (!type) {
- local_free_vars();
- YYABORT;
- }
- }
- | MAPXFN
- {
- master_notify($1);
- master_msg("X/Open Federated Naming service not supported");
- YYABORT;
- }
- | MAPNULL
- {
- if (type)
- free(type);
- type = master_strdup($1 + 1);
- if (!type) {
- local_free_vars();
- YYABORT;
- }
- }
- | dnattrs
- {
- if (type)
- free(type);
- type = master_strdup("ldap");
- if (!type) {
- local_free_vars();
- YYABORT;
- }
- tmp_argc++;
- tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
- if (!tmp_argv) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- | MAPTYPE PATH
- {
- char *tmp = NULL;
-
- trim_maptype($1);
-
- if ((tmp = strchr($1, ',')))
- *tmp++ = '\0';
-#ifndef WITH_HESIOD
- /* Map type or map type parser is hesiod */
- if (!strcmp($1, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
- master_error("hesiod support not built in");
- local_free_vars();
- YYABORT;
- }
-#endif
- if (type)
- free(type);
- if (strcmp($1, "exec"))
- type = master_strdup($1);
- else
- type = master_strdup("program");
- if (!type) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- if (tmp) {
- if (format)
- free(format);
- format = master_strdup(tmp);
- if (!format) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- tmp_argc++;
- tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
- if (!tmp_argv) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- | MAPTYPE MAPNAME
- {
- char *tmp = NULL;
-
- trim_maptype($1);
-
- if ((tmp = strchr($1, ',')))
- *tmp++ = '\0';
-
- if (type)
- free(type);
- if (strcmp($1, "exec"))
- type = master_strdup($1);
- else
- type = master_strdup("program");
- if (!type) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- if (tmp) {
- if (format)
- free(format);
- format = master_strdup(tmp);
- if (!format) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- tmp_argc++;
- tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
- if (!tmp_argv) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- | MAPTYPE dn
- {
- char *tmp = NULL;
-
- trim_maptype($1);
-
- if ((tmp = strchr($1, ',')))
- *tmp++ = '\0';
-
- if (type)
- free(type);
- if (strcmp($1, "exec"))
- type = master_strdup($1);
- else
- type = master_strdup("program");
- if (!type) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- if (tmp) {
- if (format)
- free(format);
- format = master_strdup(tmp);
- if (!format) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- tmp_argc++;
- tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
- if (!tmp_argv) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- /* Add back the type for lookup_ldap.c to handle ldaps */
- if (*tmp_argv[0]) {
- tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2);
- if (!tmp) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- strcpy(tmp, type);
- strcat(tmp, ":");
- strcat(tmp, tmp_argv[0]);
- free(tmp_argv[0]);
- tmp_argv[0] = tmp;
- }
- }
- ;
-
-dn: DNSERVER dnattrs
- {
- strcpy($$, $1);
- strcat($$, $2);
- }
- | dnattrs
- {
- strcpy($$, $1);
- }
- |
- {
- master_notify("syntax error in dn");
- YYABORT;
- }
- ;
-
-dnattrs: DNATTR EQUAL DNNAME
- {
- if (strcasecmp($1, "cn") &&
- strcasecmp($1, "ou") &&
- strcasecmp($1, "automountMapName") &&
- strcasecmp($1, "nisMapName")) {
- strcpy(errstr, $1);
- strcat(errstr, "=");
- strcat(errstr, $3);
- master_notify(errstr);
- YYABORT;
- }
- strcpy($$, $1);
- strcat($$, "=");
- strcat($$, $3);
- }
- | DNATTR EQUAL DNNAME COMMA dnattr
- {
- if (strcasecmp($1, "cn") &&
- strcasecmp($1, "ou") &&
- strcasecmp($1, "automountMapName") &&
- strcasecmp($1, "nisMapName")) {
- strcpy(errstr, $1);
- strcat(errstr, "=");
- strcat(errstr, $3);
- master_notify(errstr);
- YYABORT;
- }
- strcpy($$, $1);
- strcat($$, "=");
- strcat($$, $3);
- strcat($$, ",");
- strcat($$, $5);
- }
- | DNNAME
- {
- /* Matches map in old style syntax ldap:server:map */
- strcpy($$, $1);
- }
- | DNATTR
- {
- master_notify($1);
- YYABORT;
- }
- ;
-
-dnattr: DNATTR EQUAL DNNAME
- {
- if (!strcasecmp($1, "automountMapName") ||
- !strcasecmp($1, "nisMapName")) {
- strcpy(errstr, $1);
- strcat(errstr, "=");
- strcat(errstr, $3);
- master_notify(errstr);
- YYABORT;
- }
- strcpy($$, $1);
- strcat($$, "=");
- strcat($$, $3);
- }
- | DNATTR EQUAL DNNAME COMMA dnattr
- {
- if (!strcasecmp($1, "automountMapName") ||
- !strcasecmp($1, "nisMapName")) {
- strcpy(errstr, $1);
- strcat(errstr, "=");
- strcat(errstr, $3);
- master_notify(errstr);
- YYABORT;
- }
- strcpy($$, $1);
- strcat($$, "=");
- strcat($$, $3);
- strcat($$, ",");
- strcat($$, $5);
- }
- | DNATTR
- {
- master_notify($1);
- YYABORT;
- }
- | DNNAME
- {
- master_notify($1);
- YYABORT;
- }
- ;
-
-options: option {}
- | options COMMA option {}
- | options option {}
- | options COMMA COMMA option
- {
- master_notify($1);
- YYABORT;
- }
- | options EQUAL
- {
- master_notify($1);
- YYABORT;
- }
- ;
-
-option: daemon_option
- | mount_option {}
- | error
- {
- master_notify("bogus option");
- YYABORT;
- }
- ;
-
-daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; }
- | OPT_NTIMEOUT NUMBER { negative_timeout = $2; }
- | OPT_SYMLINK { symlnk = 1; }
- | OPT_STRICTEXPIRE { strictexpire = 1; }
- | OPT_SHARED { propagation = PROPAGATION_SHARED; }
- | OPT_SLAVE { propagation = PROPAGATION_SLAVE; }
- | OPT_PRIVATE { propagation = PROPAGATION_PRIVATE; }
- | OPT_NOBIND { nobind = 1; }
- | OPT_NOGHOST { ghost = 0; }
- | OPT_GHOST { ghost = 1; }
- | OPT_VERBOSE { verbose = 1; }
- | OPT_DEBUG { debug = 1; }
- | OPT_RANDOM { random_selection = 1; }
- | OPT_USE_WEIGHT { use_weight = 1; }
- | OPT_MODE OCTALNUMBER { mode = $2; }
- ;
-
-mount_option: OPTION
- {
- tmp_argc++;
- tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
- if (!tmp_argv) {
- master_error("memory allocation error");
- local_free_vars();
- YYABORT;
- }
- }
- ;
-%%
-
-#if YYDEBUG
-static int master_fprintf(FILE *f, char *msg, ...)
-{
- va_list ap;
- va_start(ap, msg);
- vsyslog(LOG_DEBUG, msg, ap);
- va_end(ap);
- return 1;
-}
-#endif
-
-static char *master_strdup(char *str)
-{
- char *tmp;
-
- tmp = strdup(str);
- if (!tmp)
- master_error("memory allocation error");
- return tmp;
-}
-
-static int master_error(const char *s)
-{
- logmsg("%s while parsing map.", s);
- return 0;
-}
-
-static int master_notify(const char *s)
-{
- logmsg("syntax error in map near [ %s ]", s);
- return(0);
-}
-
-static int master_msg(const char *s)
-{
- logmsg("%s", s);
- return 0;
-}
-
-static void local_init_vars(void)
-{
- path = NULL;
- type = NULL;
- format = NULL;
- verbose = 0;
- debug = 0;
- timeout = -1;
- negative_timeout = 0;
- symlnk = 0;
- strictexpire = 0;
- propagation = PROPAGATION_SLAVE;
- nobind = 0;
- ghost = defaults_get_browse_mode();
- random_selection = global_selection_options & MOUNT_FLAG_RANDOM_SELECT;
- use_weight = 0;
- mode = 0;
- tmp_argv = NULL;
- tmp_argc = 0;
- local_argv = NULL;
- local_argc = 0;
-}
-
-static void local_free_vars(void)
-{
- if (path)
- free(path);
-
- if (type)
- free(type);
-
- if (format)
- free(format);
-
- if (local_argv) {
- free_argv(local_argc, (const char **) local_argv);
- local_argv = NULL;
- local_argc = 0;
- }
-
- if (tmp_argv) {
- free_argv(tmp_argc, (const char **) tmp_argv);
- tmp_argv = NULL;
- tmp_argc = 0;
- }
-}
-
-static void trim_maptype(char *type)
-{
- char *tmp;
-
- tmp = strchr(type, ':');
- if (tmp)
- *tmp = '\0';
- else {
- int len = strlen(type);
- while (len-- && isblank(type[len]))
- type[len] = '\0';
- }
- return;
-}
-
-static int add_multi_mapstr(void)
-{
- if (type) {
- /* If type given and format is non-null add it back */
- if (format) {
- int len = strlen(type) + strlen(format) + 2;
- char *tmp = realloc(type, len);
- if (!tmp)
- return 0;
- type = tmp;
- strcat(type, ",");
- strcat(type, format);
- free(format);
- format = NULL;
- }
-
- local_argc++;
- local_argv = add_argv(local_argc, local_argv, type);
- if (!local_argv) {
- free(type);
- type = NULL;
- return 0;
- }
-
- free(type);
- type = NULL;
- }
-
- local_argv = append_argv(local_argc, local_argv, tmp_argc, tmp_argv);
- if (!local_argv) {
- free(type);
- type = NULL;
- return 0;
- }
- local_argc += tmp_argc;
-
- tmp_argc = 0;
- tmp_argv = NULL;
-
- return 1;
-}
-
-void master_init_scan(void)
-{
- lineno = 0;
-}
-
-int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigned int logging, time_t age)
-{
- struct master *master = master_list;
- struct mapent_cache *nc;
- struct master_mapent *entry, *new;
- struct map_source *source;
- unsigned int logopt = logging;
- unsigned int m_logopt = master->logopt;
- size_t mp_len;
- int ret;
-
- local_init_vars();
-
- lineno++;
-
- master_set_scan_buffer(buffer);
-
- ret = master_parse();
- if (ret != 0) {
- local_free_vars();
- return 0;
- }
-
- mp_len = strlen(path);
- while (mp_len && path[--mp_len] == '/')
- path[mp_len] = 0;
-
- nc = master->nc;
-
- /* Add null map entries to the null map cache */
- if (type && !strcmp(type, "null")) {
- cache_update(nc, NULL, path, NULL, lineno);
- local_free_vars();
- return 1;
- }
-
- /* Ignore all subsequent matching nulled entries */
- if (cache_lookup_distinct(nc, path)) {
- local_free_vars();
- return 1;
- }
-
- if (debug || verbose) {
- logopt = (debug ? LOGOPT_DEBUG : 0);
- logopt |= (verbose ? LOGOPT_VERBOSE : 0);
- }
-
- new = NULL;
- entry = master_find_mapent(master, path);
- if (!entry) {
- new = master_new_mapent(master, path, age);
- if (!new) {
- local_free_vars();
- return 0;
- }
- entry = new;
- } else {
- if (entry->age && entry->age == age) {
- if (strcmp(path, "/-")) {
- info(m_logopt,
- "ignoring duplicate indirect mount %s",
- path);
- local_free_vars();
- return 0;
- }
- }
- }
-
- if (!format) {
- if (conf_amd_mount_section_exists(path))
- format = strdup("amd");
- }
-
- if (format && !strcmp(format, "amd")) {
- unsigned int loglevel = conf_amd_get_log_options();
- unsigned int flags = conf_amd_get_flags(path);
-
- if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
- logopt = LOGOPT_DEBUG;
- else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
- logopt = LOGOPT_VERBOSE;
-
- /* It isn't possible to provide the fullybrowsable amd
- * browsing functionality within the autofs framework.
- * This flag will not be set if browsable_dirs = full
- * in the configuration or fullybrowsable is present as
- * an option.
- */
- if (flags & CONF_BROWSABLE_DIRS)
- ghost = 1;
- }
-
- if (!entry->ap) {
- ret = master_add_autofs_point(entry, logopt, nobind, ghost, 0);
- if (!ret) {
- error(m_logopt, "failed to add autofs_point");
- if (new)
- master_free_mapent(new);
- local_free_vars();
- return 0;
- }
- }
- entry->ap->flags &= ~(PROPAGATION_MASK);
- entry->ap->flags |= propagation;
-
- if (random_selection)
- entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
- if (use_weight)
- entry->ap->flags |= MOUNT_FLAG_USE_WEIGHT_ONLY;
- if (symlnk)
- entry->ap->flags |= MOUNT_FLAG_SYMLINK;
- if (strictexpire)
- entry->ap->flags |= MOUNT_FLAG_STRICTEXPIRE;
- if (negative_timeout)
- entry->ap->negative_timeout = negative_timeout;
- if (mode && mode < LONG_MAX)
- entry->ap->mode = mode;
-
- if (timeout < 0) {
- /*
- * If no timeout is given get the timout from the
- * autofs point, or the first map, or the config
- * for amd maps.
- */
- if (format && !strcmp(format, "amd"))
- timeout = conf_amd_get_dismount_interval(path);
- else
- timeout = get_exp_timeout(entry->ap, entry->maps);
- }
-
- if (format && !strcmp(format, "amd")) {
- char *opts = conf_amd_get_map_options(path);
- if (opts) {
- /* autofs uses the equivalent of cache:=inc,sync
- * (except for file maps which use cache:=all,sync)
- * but if the map is large then it may be necessary
- * to read the whole map at startup even if browsing
- * is is not enabled, so look for cache:=all in the
- * map_options configuration entry.
- */
- if (strstr(opts, "cache:=all"))
- entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
- free(opts);
- }
- }
-
-/*
- source = master_find_map_source(entry, type, format,
- local_argc, (const char **) local_argv);
- if (!source)
- source = master_add_map_source(entry, type, format, age,
- local_argc, (const char **) local_argv);
- else
- source->age = age;
-*/
- source = master_add_map_source(entry, type, format, age,
- local_argc, (const char **) local_argv);
- if (!source) {
- error(m_logopt, "failed to add source");
- if (new)
- master_free_mapent(new);
- local_free_vars();
- return 0;
- }
- set_exp_timeout(entry->ap, source, timeout);
- source->master_line = lineno;
-
- entry->age = age;
- entry->current = NULL;
-
- if (new)
- master_add_mapent(master, entry);
-
- local_free_vars();
-
- return 1;
-}
-
--- autofs-5.1.4.orig/lib/master_tok.l
+++ /dev/null
@@ -1,504 +0,0 @@
-%{
-/* ----------------------------------------------------------------------- *
- *
- * master_tok.l - master map tokenizer.
- *
- * Copyright 2006 Ian Kent <raven@themaw.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
- * USA; either version 2 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * ----------------------------------------------------------------------- */
-
-#ifdef ECHO
-# undef ECHO
-#endif /* ECHO */
-static void master_echo(void); /* forward definition */
-#define ECHO master_echo()
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include "master_parse.tab.h"
-
-/*
- * There are some things that need to be defined only if useing GNU flex.
- * These must not be defined if using standard lex
- */
-#ifdef FLEX_SCANNER
-int master_lineno;
-#endif
-
-int master_lex(void);
-int master_wrap(void);
-
-/* no need for yywrap() */
-#define YY_SKIP_YYWRAP
-
-#ifndef YY_STACK_USED
-#define YY_STACK_USED 0
-#endif
-#ifndef YY_ALWAYS_INTERACTIVE
-#define YY_ALWAYS_INTERACTIVE 0
-#endif
-#ifndef YY_NEVER_INTERACTIVE
-#define YY_NEVER_INTERACTIVE 0
-#endif
-#ifndef YY_MAIN
-#define YY_MAIN 0
-#endif
-
-void master_set_scan_buffer(const char *);
-const char *line = NULL;
-
-#ifdef FLEX_SCANNER
-const char *line_pos = NULL;
-const char *line_lim = NULL;
-int my_yyinput(char *, int);
-
-#undef YY_INPUT
-#define YY_INPUT(b, r, ms) (r = my_yyinput(b, ms))
-#else
-#undef input
-#undef unput
-#define input() (*(char *) line++)
-#define unput(c) (*(char *) --line = c)
-#endif
-
-#define BUFF_LEN 1024
-char buff[BUFF_LEN];
-char *bptr;
-char *optr = buff;
-unsigned int tlen;
-
-%}
-
-%option nounput
-
-%x PATHSTR MAPSTR DNSTR OPTSTR OCTAL
-
-WS [[:blank:]]+
-OPTWS [[:blank:]]*
-NL \r?\n
-CONT \\\n{OPTWS}
-
-OPTIONSTR ([\-]?([[:alpha:]_]([[:alnum:]_\-])*(=(\"?([[:alnum:]_\-\:\.])+\"?))?)+)
-MACROSTR (-D{OPTWS}([[:alpha:]_]([[:alnum:]_\-\.])*)=([[:alnum:]_\-\.])+)
-SLASHIFYSTR (--(no-)?slashify-colons)
-NUMBER [0-9]+
-OCTALNUMBER [0-7]+
-
-DNSERVSTR1 ([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:)
-DNSERVSTR2 (\[([[:xdigit:]]:.)+\](:[0-9]+)?:)
-DNSERVSTR3 (\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
-DNSERVSTR4 (\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/)
-DNSERVSTR5 (([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
-DNSERVSTR6 (\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
-DNSERVERSTR ({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6})
-
-AT_CN ([cC][[nN])
-AT_NMN ([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE])
-AT_AMN ([aA][uU][tT][oO][mM][oO][uU][nN][tT][Mm][aA][pP][Nn][aA][mM][eE])
-AT_OU ([oO][[uU])
-AT_DC ([dD][[cC])
-AT_O ([oO])
-AT_C ([cC])
-AT_L ([lL])
-DNATTRSTR ({AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}|{AT_L})
-DNNAMESTR1 ([[:alnum:]_.\- ]+)
-DNNAMESTR2 ([[:alnum:]_.\-]+)
-
-INTMAP (-hosts|-null)
-MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
-MULTISEP ([\-]{2}[[:blank:]]+)
-MTYPE ((file|program|exec|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS}))
-
-
-OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
-OPTNTOUT (-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeout{OPTWS}={OPTWS})
-
-MODE (--mode{OPTWS}|--mode{OPTWS}={OPTWS})
-
-%%
-
-<INITIAL>{
- {NL} |
- \x00 {
- if (optr != buff) {
- *optr = '\0';
- strcpy(master_lval.strtype, buff);
- return NILL;
- }
- }
-
- #.* { return COMMENT; }
-
- "/" {
- if (optr != buff) {
- *optr = '\0';
- strcpy(master_lval.strtype, buff);
- return NILL;
- }
- BEGIN(PATHSTR);
- bptr = buff;
- yyless(0);
- }
-
- . { *optr++ = *master_text; }
-}
-
-<PATHSTR>{
- \x00 {
- BEGIN(INITIAL);
- *bptr++ = *master_text;
- strcpy(master_lval.strtype, buff);
- return NILL;
- }
-
- \\. { *bptr++ = *(master_text + 1); }
- \" {
- BEGIN(INITIAL);
- *bptr++ = *master_text;
- *bptr = '\0';
- strcpy(master_lval.strtype, buff);
- return QUOTE;
- }
-
- {WS} {
- BEGIN(MAPSTR);
- *bptr = '\0';
- strcpy(master_lval.strtype, buff);
- bptr = buff;
- memset(buff, 0, BUFF_LEN);
- return(PATH);
- }
-
- <<EOF>> {
- BEGIN(INITIAL);
- *bptr = '\0';
- strcpy(master_lval.strtype, buff);
- return(PATH);
- }
-
- {NL} {
- BEGIN(INITIAL);
- *bptr = '\0';
- strcpy(master_lval.strtype, buff);
- return PATH;
- }
-
- . { *bptr++ = *master_text; }
-}
-
-<MAPSTR>{
- {OPTWS}\\\n{OPTWS} {}
-
- {MULTI} {
- tlen = master_leng - 1;
- if (bptr != buff && isblank(master_text[tlen])) {
- /*
- * We can't handle unescaped white space in map names
- * so just eat the white space. We always have the
- * "multi" at the beginning of the string so the while
- * will not fall off the end.
- */
- while (isblank(master_text[tlen - 1]))
- tlen--;
- strncat(buff, master_text, tlen);
- bptr += tlen;
- yyless(tlen);
- } else {
- strcpy(master_lval.strtype, master_text);
- return(MULTITYPE);
- }
- }
-
- {MTYPE} |
- {MTYPE}/{DNSERVERSTR}{DNATTRSTR}= |
- {MTYPE}/{DNATTRSTR}= {
- tlen = master_leng - 1;
- if (bptr != buff && isblank(master_text[tlen])) {
- /*
- * We can't handle unescaped white space in map names
- * so just eat the white space. We always have the
- * maptype keyword at the beginning of the string so
- * the while will not fall off the end.
- */
- while (isblank(master_text[tlen - 1]))
- tlen--;
- strncat(buff, master_text, tlen);
- bptr += tlen;
- yyless(tlen);
- } else {
- strcpy(master_lval.strtype, master_text);
- return(MAPTYPE);
- }
- }
-
- {MULTISEP} { return(DDASH); }
-
- ":" { return(COLON); }
-
- "-hosts" {
- BEGIN(OPTSTR);
- strcpy(master_lval.strtype, master_text);
- return MAPHOSTS;
- }
-
- "-null" {
- BEGIN(OPTSTR);
- strcpy(master_lval.strtype, master_text);
- return MAPNULL;
- }
-
- "-xfn" {
- /*
- * The X/Open Federated Naming service isn't supported
- * and the parser will call YYABORT() when it sees the
- * MAPXFN token so we must set the start state to the
- * INITIAL state here for the next yylex() call.
- */
- BEGIN(INITIAL);
- strcpy(master_lval.strtype, master_text);
- return MAPXFN;
- }
-
- "//" {
- BEGIN(DNSTR);
- yyless(0);
- }
-
- {DNSERVERSTR}{DNATTRSTR}= {
- BEGIN(DNSTR);
- yyless(0);
- }
-
- {DNATTRSTR}= {
- BEGIN(DNSTR);
- yyless(0);
- }
-
- {OPTWS}/{NL} {
- BEGIN(INITIAL);
- *bptr = '\0';
- strcpy(master_lval.strtype, buff);
- bptr = buff;
- return(MAPNAME);
- }
-
- \\. { *bptr++ = *(master_text + 1); }
-
- {WS} {
- BEGIN(OPTSTR);
- *bptr = '\0';
- strcpy(master_lval.strtype, buff);
- bptr = buff;
- return(MAPNAME);
- }
-
- {NL} |
- \x00 {
- BEGIN(INITIAL);
- *bptr = '\0';
- strcpy(master_lval.strtype, buff);
- return(MAPNAME);
- }
-
- <<EOF>> {
- BEGIN(INITIAL);
- *bptr = '\0';
- strcpy(master_lval.strtype, buff);
- return(MAPNAME);
- }
-
- . { *bptr++ = *master_text; }
-}
-
-<DNSTR>{
- {OPTWS}\\\n{OPTWS} {}
-
- {DNSERVERSTR} {
- strcpy(master_lval.strtype, master_text);
- return DNSERVER;
- }
-
- {DNATTRSTR}/"=" {
- strcpy(master_lval.strtype, master_text);
- return DNATTR;
- }
-
- "=" {
- return EQUAL;
- }
-
- {DNNAMESTR1}/","{DNATTRSTR}"=" {
- strcpy(master_lval.strtype, master_text);
- return DNNAME;
- }
-
- {DNNAMESTR2} {
- strcpy(master_lval.strtype, master_text);
- return DNNAME;
- }
-
- {OPTWS}","{OPTWS} {
- return COMMA;
- }
-
- {WS}"=" |
- "="{WS} {
- BEGIN(INITIAL);
- strcpy(master_lval.strtype, master_text);
- return SPACE;
- }
-
- {WS} { BEGIN(OPTSTR); }
-
- {NL} |
- \x00 { BEGIN(INITIAL); }
-
- <<EOF>> { BEGIN(INITIAL); }
-}
-
-<OPTSTR>{
- {OPTWS}\\\n{OPTWS} {}
-
- {MULTISEP} {
- BEGIN(MAPSTR);
- return(DDASH);
- }
-
- {OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); }
-
- {OPTNTOUT}/{NUMBER} { return(OPT_NTIMEOUT); }
-
- {NUMBER} {
- master_lval.longtype = atol(master_text);
- return(NUMBER);
- }
-
- -?symlink { return(OPT_SYMLINK); }
- -?nobind { return(OPT_NOBIND); }
- -?nobrowse { return(OPT_NOGHOST); }
- -?shared { return(OPT_SHARED); }
- -?slave { return(OPT_SLAVE); }
- -?private { return(OPT_PRIVATE); }
- -?strictexpire { return(OPT_STRICTEXPIRE); }
- -g|--ghost|-?browse { return(OPT_GHOST); }
- -v|--verbose { return(OPT_VERBOSE); }
- -d|--debug { return(OPT_DEBUG); }
- -w|--use-weight-only { return(OPT_USE_WEIGHT); }
- -r|--random-multimount-selection { return(OPT_RANDOM); }
-
- {MODE}/{OCTALNUMBER} {
- BEGIN(OCTAL);
- return(OPT_MODE);
- }
-
- {OPTWS}","{OPTWS} { return(COMMA); }
-
- {OPTWS} {}
-
- {SLASHIFYSTR} {
- strcpy(master_lval.strtype, master_text);
- return(OPTION);
- }
-
- {MACROSTR} {
- strcpy(master_lval.strtype, master_text);
- return(OPTION);
- }
-
- {OPTIONSTR} {
- strcpy(master_lval.strtype, master_text);
- return(OPTION);
- }
-
- "=" {
- strcpy(master_lval.strtype, master_text);
- return(EQUAL);
- }
-
- {WS} {}
- {NL} |
- \x00 { BEGIN(INITIAL); }
-
- <<EOF>> { BEGIN(INITIAL); }
-}
-
-<OCTAL>{
- {OCTALNUMBER} {
- master_lval.longtype = strtoul(master_text, NULL, 8);
- return(OCTALNUMBER);
- }
-
- . { BEGIN(OPTSTR); yyless(0); }
-}
-
-%%
-
-#include "automount.h"
-
-int master_wrap(void)
-{
- return 1;
-}
-
-static void master_echo(void)
-{
- logmsg("%s", master_text);
- return;
-}
-
-#ifdef FLEX_SCANNER
-
-void master_set_scan_buffer(const char *buffer)
-{
- memset(buff, 0, sizeof(buff));
- optr = buff;
-
- YY_FLUSH_BUFFER;
-
- line = buffer;
- line_pos = &line[0];
- /*
- * Ensure buffer is 1 greater than string and is zeroed before
- * the parse so we can fit the extra NULL which allows us to
- * explicitly match an end of line within the buffer (ie. the
- * need for 2 NULLS when parsing in memeory buffers).
- */
- line_lim = line + strlen(buffer) + 1;
-}
-
-#ifndef min
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-int my_yyinput(char *buffer, int max_size)
-{
- int n = min(max_size, line_lim - line_pos);
-
- if (n > 0) {
- memcpy(buffer, line_pos, n);
- line_pos += n;
- }
- return n;
-}
-
-#else
-
-void master_set_scan_buffer(const char *buffer)
-{
- line = buffer;
-}
-
-#endif