6878 lines
145 KiB
Diff
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
|