Blame lib/master.c

Packit 8480eb
/* ----------------------------------------------------------------------- *
Packit 8480eb
 *   
Packit 8480eb
 *  master.c - master map utility routines.
Packit 8480eb
 *
Packit 8480eb
 *   Copyright 2006 Ian Kent <raven@themaw.net>
Packit 8480eb
 *
Packit 8480eb
 *   This program is free software; you can redistribute it and/or modify
Packit 8480eb
 *   it under the terms of the GNU General Public License as published by
Packit 8480eb
 *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
Packit 8480eb
 *   USA; either version 2 of the License, or (at your option) any later
Packit 8480eb
 *   version.
Packit 8480eb
 *   
Packit 8480eb
 *   This program is distributed in the hope that it will be useful,
Packit 8480eb
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8480eb
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8480eb
 *   GNU General Public License for more details.
Packit 8480eb
 *
Packit 8480eb
 * ----------------------------------------------------------------------- */
Packit 8480eb
Packit 8480eb
#include <stdlib.h>
Packit 8480eb
#include <string.h>
Packit 8480eb
#include <memory.h>
Packit 8480eb
#include <limits.h>
Packit 8480eb
#include <signal.h>
Packit 8480eb
#include <sys/types.h>
Packit 8480eb
#include <sys/stat.h>
Packit 8480eb
#include <ctype.h>
Packit 8480eb
#include "automount.h"
Packit 8480eb
Packit 8480eb
/* The root of the map entry tree */
Packit 8480eb
struct master *master_list = NULL;
Packit 8480eb
Packit 8480eb
extern const char *global_options;
Packit 8480eb
extern long global_negative_timeout;
Packit 8480eb
Packit 8480eb
/* Attribute to create a joinable thread */
Packit 8480eb
extern pthread_attr_t th_attr;
Packit 8480eb
Packit 8480eb
extern struct startup_cond suc;
Packit 8480eb
Packit 8480eb
static struct map_source *
Packit 8480eb
__master_find_map_source(struct master_mapent *,
Packit 8480eb
			 const char *, const char *, int, const char **);
Packit 8480eb
Packit 8480eb
static pthread_mutex_t master_mutex = PTHREAD_MUTEX_INITIALIZER;
Packit 8480eb
static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
Packit 8480eb
Packit 8480eb
void master_mutex_lock(void)
Packit 8480eb
{
Packit 8480eb
	int status = pthread_mutex_lock(&master_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_mutex_unlock(void)
Packit 8480eb
{
Packit 8480eb
	int status = pthread_mutex_unlock(&master_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_mutex_lock_cleanup(void *arg)
Packit 8480eb
{
Packit 8480eb
	master_mutex_unlock();
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
Packit 8480eb
			    unsigned nobind, unsigned ghost, int submount)
Packit 8480eb
{
Packit 8480eb
	struct autofs_point *ap;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	ap = malloc(sizeof(struct autofs_point));
Packit 8480eb
	if (!ap)
Packit 8480eb
		return 0;
Packit 8480eb
Packit 8480eb
	ap->state = ST_INIT;
Packit 8480eb
Packit 8480eb
	ap->state_pipe[0] = -1;
Packit 8480eb
	ap->state_pipe[1] = -1;
Packit 8480eb
	ap->logpri_fifo = -1;
Packit 8480eb
Packit 8480eb
	ap->path = strdup(entry->path);
Packit 8480eb
	if (!ap->path) {
Packit 8480eb
		free(ap);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
	ap->pref = NULL;
Packit 8480eb
Packit 8480eb
	ap->entry = entry;
Packit 8480eb
	ap->exp_thread = 0;
Packit 8480eb
	ap->readmap_thread = 0;
Packit 8480eb
	/*
Packit 8480eb
	 * Program command line option overrides config.
Packit 8480eb
	 * We can't use 0 negative timeout so use default.
Packit 8480eb
	 */
Packit 8480eb
	if (global_negative_timeout <= 0)
Packit 8480eb
		ap->negative_timeout = defaults_get_negative_timeout();
Packit 8480eb
	else
Packit 8480eb
		ap->negative_timeout = global_negative_timeout;
Packit 8480eb
	ap->exp_timeout = defaults_get_timeout();
Packit 8480eb
	ap->exp_runfreq = 0;
Packit 121cba
	ap->flags = MOUNT_FLAG_IGNORE;
Packit 8480eb
	if (ghost)
Packit 121cba
		ap->flags |= MOUNT_FLAG_GHOST;
Packit 8480eb
Packit 8480eb
	if (nobind)
Packit 8480eb
		ap->flags |= MOUNT_FLAG_NOBIND;
Packit 8480eb
Packit 8480eb
	if (ap->path[1] == '-')
Packit 8480eb
		ap->type = LKP_DIRECT;
Packit 8480eb
	else
Packit 8480eb
		ap->type = LKP_INDIRECT;
Packit 8480eb
Packit 8480eb
	ap->logopt = logopt;
Packit 8480eb
Packit 8480eb
	ap->parent = NULL;
Packit 8480eb
	ap->thid = 0;
Packit 8480eb
	ap->submnt_count = 0;
Packit 8480eb
	ap->submount = submount;
Packit 8480eb
	INIT_LIST_HEAD(&ap->mounts);
Packit 8480eb
	INIT_LIST_HEAD(&ap->submounts);
Packit 8480eb
	INIT_LIST_HEAD(&ap->amdmounts);
Packit 8480eb
	ap->shutdown = 0;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_init(&ap->mounts_mutex, NULL);
Packit 8480eb
	if (status) {
Packit 8480eb
		free(ap->path);
Packit 8480eb
		free(ap);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
	ap->mode = 0;
Packit 8480eb
Packit 8480eb
	entry->ap = ap;
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_free_autofs_point(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	struct list_head *p, *head;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	if (!ap)
Packit 8480eb
		return;
Packit 8480eb
Packit 8480eb
	mounts_mutex_lock(ap);
Packit 8480eb
	head = &ap->amdmounts;
Packit 8480eb
	p = head->next;
Packit 8480eb
	while (p != head) {
Packit 8480eb
		struct amd_entry *entry = list_entry(p, struct amd_entry, entries);
Packit 8480eb
		p = p->next;
Packit 8480eb
		if (!list_empty(&entry->ext_mount))
Packit 8480eb
			ext_mount_remove(&entry->ext_mount, entry->fs);
Packit 8480eb
		if (!list_empty(&entry->entries))
Packit 8480eb
			list_del(&entry->entries);
Packit d47386
		free_amd_entry(entry);
Packit 8480eb
	}
Packit 8480eb
	mounts_mutex_unlock(ap);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_destroy(&ap->mounts_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	if (ap->pref)
Packit 8480eb
		free(ap->pref);
Packit 8480eb
	free(ap->path);
Packit 8480eb
	free(ap);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct map_source *
Packit 8480eb
master_add_map_source(struct master_mapent *entry,
Packit 8480eb
		      char *type, char *format, time_t age,
Packit 8480eb
		      int argc, const char **argv)
Packit 8480eb
{
Packit 8480eb
	struct map_source *source;
Packit 8480eb
	char *ntype, *nformat;
Packit 8480eb
	const char **tmpargv;
Packit 8480eb
Packit 8480eb
	source = malloc(sizeof(struct map_source));
Packit 8480eb
	if (!source)
Packit 8480eb
		return NULL;
Packit 8480eb
	memset(source, 0, sizeof(struct map_source));
Packit 8480eb
	source->ref = 1;
Packit 8480eb
Packit 8480eb
	if (type) {
Packit 8480eb
		ntype = strdup(type);
Packit 8480eb
		if (!ntype) {
Packit 8480eb
			master_free_map_source(source, 0);
Packit 8480eb
			return NULL;
Packit 8480eb
		}
Packit 8480eb
		source->type = ntype;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (format) {
Packit 8480eb
		nformat = strdup(format);
Packit 8480eb
		if (!nformat) {
Packit 8480eb
			master_free_map_source(source, 0);
Packit 8480eb
			return NULL;
Packit 8480eb
		}
Packit 8480eb
		source->format = nformat;
Packit 8480eb
		if (!strcmp(nformat, "amd"))
Packit 8480eb
			source->flags |= MAP_FLAG_FORMAT_AMD;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	source->age = age;
Packit 8480eb
	source->stale = 1;
Packit 8480eb
Packit 8480eb
	tmpargv = copy_argv(argc, argv);
Packit 8480eb
	if (!tmpargv) {
Packit 8480eb
		master_free_map_source(source, 0);
Packit 8480eb
		return NULL;
Packit 8480eb
	}
Packit 8480eb
	source->argc = argc;
Packit 8480eb
	source->argv = tmpargv;
Packit 8480eb
	if (source->argv[0])
Packit 8480eb
		source->name = strdup(source->argv[0]);
Packit 8480eb
Packit 8480eb
	master_source_writelock(entry);
Packit 8480eb
Packit 8480eb
	if (!entry->maps) {
Packit 8480eb
		source->mc = cache_init(entry->ap, source);
Packit 8480eb
		if (!source->mc) {
Packit 8480eb
			master_free_map_source(source, 0);
Packit 8480eb
			master_source_unlock(entry);
Packit 8480eb
			return NULL;
Packit 8480eb
		}
Packit 8480eb
		entry->maps = source;
Packit 8480eb
	} else {
Packit 8480eb
		struct map_source *this, *last, *next;
Packit 8480eb
Packit 8480eb
		/* Typically there only a few map sources */
Packit 8480eb
Packit 8480eb
		this = __master_find_map_source(entry, type, format, argc, tmpargv);
Packit 8480eb
		if (this) {
Packit 8480eb
			debug(entry->ap->logopt,
Packit 8480eb
			      "map source used without taking reference");
Packit 8480eb
			this->age = age;
Packit 8480eb
			master_free_map_source(source, 0);
Packit 8480eb
			master_source_unlock(entry);
Packit 8480eb
			return this;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		source->mc = cache_init(entry->ap, source);
Packit 8480eb
		if (!source->mc) {
Packit 8480eb
			master_free_map_source(source, 0);
Packit 8480eb
			master_source_unlock(entry);
Packit 8480eb
			return NULL;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		last = NULL;
Packit 8480eb
		next = entry->maps;
Packit 8480eb
		while (next) {
Packit 8480eb
			last = next;
Packit 8480eb
			next = next->next;
Packit 8480eb
		}
Packit 8480eb
		if (last)
Packit 8480eb
			last->next = source;
Packit 8480eb
		else
Packit 8480eb
			entry->maps = source;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	master_source_unlock(entry);
Packit 8480eb
Packit 8480eb
	return source;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int compare_source_type_and_format(struct map_source *map, const char *type, const char *format)
Packit 8480eb
{
Packit 8480eb
	int res = 0;
Packit 8480eb
Packit 8480eb
	if (type) {
Packit 8480eb
		if (!map->type)
Packit 8480eb
			goto done;
Packit 8480eb
Packit 8480eb
		if (strcmp(map->type, type))
Packit 8480eb
			goto done;
Packit 8480eb
	} else if (map->type)
Packit 8480eb
		goto done;
Packit 8480eb
Packit 8480eb
	if (format) {
Packit 8480eb
		if (!map->format)
Packit 8480eb
			goto done;
Packit 8480eb
Packit 8480eb
		if (strcmp(map->format, format))
Packit 8480eb
			goto done;
Packit 8480eb
	} else if (map->format)
Packit 8480eb
		goto done;
Packit 8480eb
Packit 8480eb
	res = 1;
Packit 8480eb
done:
Packit 8480eb
	return res;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static struct map_source *
Packit 8480eb
__master_find_map_source(struct master_mapent *entry,
Packit 8480eb
			 const char *type, const char *format,
Packit 8480eb
			 int argc, const char **argv)
Packit 8480eb
{
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	struct map_source *source = NULL;
Packit 8480eb
	int res;
Packit 8480eb
Packit 8480eb
	map = entry->maps;
Packit 8480eb
	while (map) {
Packit 8480eb
		res = compare_source_type_and_format(map, type, format);
Packit 8480eb
		if (!res)
Packit 8480eb
			goto next;
Packit 8480eb
Packit 8480eb
		res = compare_argv(map->argc, map->argv, argc, argv);
Packit 8480eb
		if (!res)
Packit 8480eb
			goto next;
Packit 8480eb
Packit 8480eb
		source = map;
Packit 8480eb
		break;
Packit 8480eb
next:
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return source;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct map_source *master_find_map_source(struct master_mapent *entry,
Packit 8480eb
				const char *type, const char *format,
Packit 8480eb
				int argc, const char **argv)
Packit 8480eb
{
Packit 8480eb
	struct map_source *source = NULL;
Packit 8480eb
Packit 8480eb
	master_source_readlock(entry);
Packit 8480eb
	source = __master_find_map_source(entry, type, format, argc, argv);
Packit 8480eb
	master_source_unlock(entry);
Packit 8480eb
Packit 8480eb
	return source;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct map_source *
Packit 8480eb
master_get_map_source(struct master_mapent *entry,
Packit 8480eb
		      const char *type, const char *format,
Packit 8480eb
		      int argc, const char **argv)
Packit 8480eb
{
Packit 8480eb
	struct map_source *source = NULL;
Packit 8480eb
Packit 8480eb
	master_source_readlock(entry);
Packit 8480eb
	source = __master_find_map_source(entry, type, format, argc, argv);
Packit 8480eb
	if (source)
Packit 8480eb
		source->ref++;
Packit 8480eb
	master_source_unlock(entry);
Packit 8480eb
Packit 8480eb
	return source;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void __master_free_map_source(struct map_source *source, unsigned int free_cache)
Packit 8480eb
{
Packit 8480eb
	/* instance map sources are not ref counted */
Packit 8480eb
	if (source->ref && --source->ref)
Packit 8480eb
		return;
Packit 8480eb
	if (source->type)
Packit 8480eb
		free(source->type);
Packit 8480eb
	if (source->format)
Packit 8480eb
		free(source->format);
Packit 8480eb
	if (source->name)
Packit 8480eb
		free(source->name);
Packit 8480eb
	if (free_cache && source->mc)
Packit 8480eb
		cache_release(source);
Packit 8480eb
	if (source->lookup) {
Packit 8480eb
		struct map_source *instance;
Packit 8480eb
Packit 8480eb
		instance = source->instance;
Packit 8480eb
		while (instance) {
Packit 8480eb
			if (instance->lookup)
Packit 8480eb
				close_lookup(instance->lookup);
Packit 8480eb
			instance = instance->next;
Packit 8480eb
		}
Packit 8480eb
		close_lookup(source->lookup);
Packit 8480eb
	}
Packit 8480eb
	if (source->argv)
Packit 8480eb
		free_argv(source->argc, source->argv);
Packit 8480eb
	if (source->instance) {
Packit 8480eb
		struct map_source *instance, *next;
Packit 8480eb
Packit 8480eb
		instance = source->instance;
Packit 8480eb
		while (instance) {
Packit 8480eb
			next = instance->next;
Packit 8480eb
			__master_free_map_source(instance, 0);
Packit 8480eb
			instance = next;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	free(source);
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_free_map_source(struct map_source *source, unsigned int free_cache)
Packit 8480eb
{
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&instance_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	__master_free_map_source(source, free_cache);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&instance_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct map_source *master_find_source_instance(struct map_source *source, const char *type, const char *format, int argc, const char **argv)
Packit 8480eb
{
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	struct map_source *instance = NULL;
Packit 8480eb
	int status, res;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&instance_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	map = source->instance;
Packit 8480eb
	while (map) {
Packit 8480eb
		res = compare_source_type_and_format(map, type, format);
Packit 8480eb
		if (!res)
Packit 8480eb
			goto next;
Packit 8480eb
Packit 8480eb
		if (!argv) {
Packit 8480eb
			instance = map;
Packit 8480eb
			break;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		res = compare_argv(map->argc, map->argv, argc, argv);
Packit 8480eb
		if (!res)
Packit 8480eb
			goto next;
Packit 8480eb
Packit 8480eb
		instance = map;
Packit 8480eb
		break;
Packit 8480eb
next:
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&instance_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	return instance;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct map_source *
Packit 8480eb
master_add_source_instance(struct map_source *source, const char *type, const char *format, time_t age, int argc, const char **argv)
Packit 8480eb
{
Packit 8480eb
	struct map_source *instance;
Packit 8480eb
	struct map_source *new;
Packit 8480eb
	char *ntype, *nformat;
Packit 8480eb
	const char **tmpargv;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	instance = master_find_source_instance(source, type, format, argc, argv);
Packit 8480eb
	if (instance)
Packit 8480eb
		return instance;
Packit 8480eb
Packit 8480eb
	new = malloc(sizeof(struct map_source));
Packit 8480eb
	if (!new)
Packit 8480eb
		return NULL;
Packit 8480eb
	memset(new, 0, sizeof(struct map_source));
Packit 8480eb
Packit 8480eb
	if (type) {
Packit 8480eb
		ntype = strdup(type);
Packit 8480eb
		if (!ntype) {
Packit 8480eb
			master_free_map_source(new, 0);
Packit 8480eb
			return NULL;
Packit 8480eb
		}
Packit 8480eb
		new->type = ntype;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (format) {
Packit 8480eb
		nformat = strdup(format);
Packit 8480eb
		if (!nformat) {
Packit 8480eb
			master_free_map_source(new, 0);
Packit 8480eb
			return NULL;
Packit 8480eb
		}
Packit 8480eb
		new->format = nformat;
Packit 8480eb
		if (!strcmp(nformat, "amd"))
Packit 8480eb
			new->flags |= MAP_FLAG_FORMAT_AMD;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	new->age = age;
Packit 8480eb
	new->master_line = 0;
Packit 8480eb
	new->mc = source->mc;
Packit 8480eb
	new->exp_timeout = source->exp_timeout;
Packit 8480eb
	new->stale = 1;
Packit 8480eb
Packit 8480eb
	tmpargv = copy_argv(argc, argv);
Packit 8480eb
	if (!tmpargv) {
Packit 8480eb
		master_free_map_source(new, 0);
Packit 8480eb
		return NULL;
Packit 8480eb
	}
Packit 8480eb
	new->argc = argc;
Packit 8480eb
	new->argv = tmpargv;
Packit 8480eb
	if (source->name)
Packit 8480eb
		new->name = strdup(source->name);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&instance_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	if (!source->instance)
Packit 8480eb
		source->instance = new;
Packit 8480eb
	else {
Packit 8480eb
		/*
Packit 8480eb
		 * We know there's no other instance of this
Packit 8480eb
		 * type so just add to head of list
Packit 8480eb
		 */
Packit 8480eb
		new->next = source->instance;
Packit 8480eb
		source->instance = new;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&instance_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	return new;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int check_stale_instances(struct map_source *source)
Packit 8480eb
{
Packit 8480eb
	struct map_source *map;
Packit 8480eb
Packit 8480eb
	if (!source)
Packit 8480eb
		return 0;
Packit 8480eb
Packit 8480eb
	map = source->instance;
Packit 8480eb
	while (map) {
Packit 8480eb
		if (map->stale)
Packit 8480eb
			return 1;
Packit 8480eb
		if (check_stale_instances(map))
Packit 8480eb
			return 1;
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void clear_stale_instances(struct map_source *source)
Packit 8480eb
{
Packit 8480eb
	struct map_source *map;
Packit 8480eb
Packit 8480eb
	if (!source)
Packit 8480eb
		return;
Packit 8480eb
Packit 8480eb
	map = source->instance;
Packit 8480eb
	while (map) {
Packit 8480eb
		clear_stale_instances(map);
Packit 8480eb
		if (map->stale)
Packit 8480eb
			map->stale = 0;
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void send_map_update_request(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	int status, need_update = 0;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&instance_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	map = ap->entry->maps;
Packit 8480eb
	while (map) {
Packit 8480eb
		if (check_stale_instances(map))
Packit 8480eb
			map->stale = 1;
Packit 8480eb
		if (map->stale) {
Packit 8480eb
			need_update = 1;
Packit 8480eb
			break;
Packit 8480eb
		}
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&instance_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	if (!need_update)
Packit 8480eb
		return;
Packit 8480eb
Packit 8480eb
	st_add_task(ap, ST_READMAP);
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_source_writelock(struct master_mapent *entry)
Packit 8480eb
{
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_rwlock_wrlock(&entry->source_lock);
Packit 8480eb
	if (status) {
Packit 8480eb
		logmsg("master_mapent source write lock failed");
Packit 8480eb
		fatal(status);
Packit 8480eb
	}
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_source_readlock(struct master_mapent *entry)
Packit 8480eb
{
Packit 8480eb
	int retries = 25;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	while (retries--) {
Packit 8480eb
		status = pthread_rwlock_rdlock(&entry->source_lock);
Packit 8480eb
		if (status != EAGAIN && status != EBUSY)
Packit 8480eb
			break;
Packit 8480eb
		else {
Packit 8480eb
                	struct timespec t = { 0, 200000000 };
Packit 8480eb
	                struct timespec r;
Packit 8480eb
Packit 8480eb
			if (status == EAGAIN)
Packit 8480eb
				logmsg("master_mapent source too many readers");
Packit 8480eb
			else
Packit 8480eb
				logmsg("master_mapent source write lock held");
Packit 8480eb
Packit 8480eb
                	while (nanosleep(&t, &r) == -1 && errno == EINTR)
Packit 8480eb
                        	memcpy(&t, &r, sizeof(struct timespec));
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (status) {
Packit 8480eb
		logmsg("master_mapent source read lock failed");
Packit 8480eb
		fatal(status);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_source_unlock(struct master_mapent *entry)
Packit 8480eb
{
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_rwlock_unlock(&entry->source_lock);
Packit 8480eb
	if (status) {
Packit 8480eb
		logmsg("master_mapent source unlock failed");
Packit 8480eb
		fatal(status);
Packit 8480eb
	}
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_source_lock_cleanup(void *arg)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry = (struct master_mapent *) arg;
Packit 8480eb
Packit 8480eb
	master_source_unlock(entry);
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_source_current_wait(struct master_mapent *entry)
Packit 8480eb
{
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&entry->current_mutex);
Packit 8480eb
	if (status) {
Packit 8480eb
		logmsg("entry current source lock failed");
Packit 8480eb
		fatal(status);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	while (entry->current != NULL) {
Packit 8480eb
		status = pthread_cond_wait(
Packit 8480eb
				&entry->current_cond, &entry->current_mutex);
Packit 8480eb
		if (status) {
Packit 8480eb
			logmsg("entry current source condition wait failed");
Packit 8480eb
			fatal(status);
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_source_current_signal(struct master_mapent *entry)
Packit 8480eb
{
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_cond_signal(&entry->current_cond);
Packit 8480eb
	if (status) {
Packit 8480eb
		logmsg("entry current source condition signal failed");
Packit 8480eb
		fatal(status);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&entry->current_mutex);
Packit 8480eb
	if (status) {
Packit 8480eb
		logmsg("entry current source unlock failed");
Packit 8480eb
		fatal(status);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct master_mapent *master_find_mapent(struct master *master, const char *path)
Packit 8480eb
{
Packit 8480eb
	struct list_head *head, *p;
Packit 8480eb
Packit 8480eb
	head = &master->mounts;
Packit 8480eb
	list_for_each(p, head) {
Packit 8480eb
		struct master_mapent *entry;
Packit 8480eb
Packit 8480eb
		entry = list_entry(p, struct master_mapent, list);
Packit 8480eb
Packit 8480eb
		if (!strcmp(entry->path, path))
Packit 8480eb
			return entry;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return NULL;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
unsigned int master_partial_match_mapent(struct master *master, const char *path)
Packit 8480eb
{
Packit 8480eb
	struct list_head *head, *p;
Packit 8480eb
	size_t path_len = strlen(path);
Packit 8480eb
	int ret = 0;
Packit 8480eb
Packit 8480eb
	head = &master->mounts;
Packit 8480eb
	list_for_each(p, head) {
Packit 8480eb
		struct master_mapent *entry;
Packit 8480eb
		size_t entry_len;
Packit 8480eb
		size_t cmp_len;
Packit 8480eb
Packit 8480eb
		entry = list_entry(p, struct master_mapent, list);
Packit 8480eb
Packit 8480eb
		entry_len = strlen(entry->path);
Packit 8480eb
		cmp_len = min(entry_len, path_len);
Packit 8480eb
Packit 8480eb
		if (!strncmp(entry->path, path, cmp_len)) {
Packit 8480eb
			/* paths are equal, matching master map entry ? */
Packit 8480eb
			if (entry_len == path_len) {
Packit 8480eb
				if (entry->maps &&
Packit 8480eb
				    entry->maps->flags & MAP_FLAG_FORMAT_AMD)
Packit 8480eb
					ret = 1;
Packit 8480eb
				else
Packit 8480eb
					ret = -1;
Packit 8480eb
				break;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			/* amd mount conflicts with entry mount */
Packit 8480eb
			if (entry_len > path_len &&
Packit 8480eb
			    *(entry->path + path_len) == '/') {
Packit 8480eb
				ret = -1;
Packit 8480eb
				break;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			/* entry mount conflicts with amd mount */
Packit 8480eb
			if (entry_len < path_len &&
Packit 8480eb
			    *(path + entry_len) == '/') {
Packit 8480eb
				ret = -1;
Packit 8480eb
				break;
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct autofs_point *__master_find_submount(struct autofs_point *ap, const char *path)
Packit 8480eb
{
Packit 8480eb
	struct list_head *head, *p;
Packit 8480eb
Packit 8480eb
	head = &ap->submounts;
Packit 8480eb
	list_for_each(p, head) {
Packit 8480eb
		struct autofs_point *submount;
Packit 8480eb
Packit 8480eb
		submount = list_entry(p, struct autofs_point, mounts);
Packit 8480eb
Packit 8480eb
		if (!strcmp(submount->path, path))
Packit 8480eb
			return submount;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return NULL;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct autofs_point *master_find_submount(struct autofs_point *ap, const char *path)
Packit 8480eb
{
Packit 8480eb
	struct autofs_point *submount;
Packit 8480eb
Packit 8480eb
	mounts_mutex_lock(ap);
Packit 8480eb
	submount = __master_find_submount(ap, path);
Packit 8480eb
	mounts_mutex_unlock(ap);
Packit 8480eb
Packit 8480eb
	return submount;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct amd_entry *__master_find_amdmount(struct autofs_point *ap, const char *path)
Packit 8480eb
{
Packit 8480eb
	struct list_head *head, *p;
Packit 8480eb
Packit 8480eb
	head = &ap->amdmounts;
Packit 8480eb
	list_for_each(p, head) {
Packit 8480eb
		struct amd_entry *entry;
Packit 8480eb
Packit 8480eb
		entry = list_entry(p, struct amd_entry, entries);
Packit 8480eb
Packit 8480eb
		if (!strcmp(entry->path, path))
Packit 8480eb
			return entry;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return NULL;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct amd_entry *master_find_amdmount(struct autofs_point *ap, const char *path)
Packit 8480eb
{
Packit 8480eb
	struct amd_entry *entry;
Packit 8480eb
Packit 8480eb
	mounts_mutex_lock(ap);
Packit 8480eb
	entry = __master_find_amdmount(ap, path);
Packit 8480eb
	mounts_mutex_unlock(ap);
Packit 8480eb
Packit 8480eb
	return entry;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry;
Packit 8480eb
	int status;
Packit 8480eb
	char *tmp;
Packit 8480eb
Packit 8480eb
	entry = malloc(sizeof(struct master_mapent));
Packit 8480eb
	if (!entry)
Packit 8480eb
		return NULL;
Packit 8480eb
Packit 8480eb
	memset(entry, 0, sizeof(struct master_mapent));
Packit 8480eb
Packit 8480eb
	tmp = strdup(path);
Packit 8480eb
	if (!tmp) {
Packit 8480eb
		free(entry);
Packit 8480eb
		return NULL;
Packit 8480eb
	}
Packit 8480eb
	entry->path = tmp;
Packit 8480eb
Packit 8480eb
	entry->thid = 0;
Packit 8480eb
	entry->age = age;
Packit 8480eb
	entry->master = master;
Packit 8480eb
	entry->current = NULL;
Packit 8480eb
	entry->maps = NULL;
Packit 8480eb
	entry->ap = NULL;
Packit 8480eb
Packit 8480eb
	status = pthread_rwlock_init(&entry->source_lock, NULL);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_init(&entry->current_mutex, NULL);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	status = pthread_cond_init(&entry->current_cond, NULL);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	INIT_LIST_HEAD(&entry->list);
Packit 8480eb
Packit 8480eb
	return entry;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_add_mapent(struct master *master, struct master_mapent *entry)
Packit 8480eb
{
Packit 8480eb
	list_add_tail(&entry->list, &master->mounts);
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_remove_mapent(struct master_mapent *entry)
Packit 8480eb
{
Packit 8480eb
	struct master *master = entry->master;
Packit 8480eb
Packit 8480eb
	if (entry->ap->submount)
Packit 8480eb
		return;
Packit 8480eb
Packit 8480eb
	if (!list_empty(&entry->list)) {
Packit 8480eb
		list_del_init(&entry->list);
Packit 8480eb
		list_add(&entry->join, &master->completed);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_free_mapent_sources(struct master_mapent *entry, unsigned int free_cache)
Packit 8480eb
{
Packit 8480eb
	if (entry->maps) {
Packit 8480eb
		struct map_source *m, *n;
Packit 8480eb
Packit 8480eb
		m = entry->maps;
Packit 8480eb
		while (m) {
Packit 8480eb
			n = m->next;
Packit 8480eb
			master_free_map_source(m, free_cache);
Packit 8480eb
			m = n;
Packit 8480eb
		}
Packit 8480eb
		entry->maps = NULL;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_free_mapent(struct master_mapent *entry)
Packit 8480eb
{
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	if (entry->path)
Packit 8480eb
		free(entry->path);
Packit 8480eb
Packit 8480eb
	master_free_autofs_point(entry->ap);
Packit 8480eb
Packit 8480eb
	status = pthread_rwlock_destroy(&entry->source_lock);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_destroy(&entry->current_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	status = pthread_cond_destroy(&entry->current_cond);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	free(entry);
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 756a1b
struct master *master_new(const char *name, unsigned int timeout, unsigned int flags)
Packit 8480eb
{
Packit 8480eb
	struct master *master;
Packit 8480eb
	char *tmp;
Packit 8480eb
Packit 8480eb
	master = malloc(sizeof(struct master));
Packit 8480eb
	if (!master)
Packit 8480eb
		return NULL;
Packit 8480eb
Packit 8480eb
	if (!name)
Packit 8480eb
		tmp = (char *) defaults_get_master_map();
Packit 8480eb
	else
Packit 8480eb
		tmp = strdup(name);
Packit 8480eb
Packit 8480eb
	if (!tmp) {
Packit 8480eb
		free(master);
Packit 8480eb
		return NULL;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	master->name = tmp;
Packit 8480eb
	master->nc = NULL;
Packit 8480eb
Packit 8480eb
	master->recurse = 0;
Packit 8480eb
	master->depth = 0;
Packit 8480eb
	master->reading = 0;
Packit 8480eb
	master->read_fail = 0;
Packit 756a1b
	master->default_ghost = flags & DAEMON_FLAGS_GHOST;
Packit 8480eb
	master->default_timeout = timeout;
Packit 8480eb
	master->default_logging = defaults_get_logging();
Packit 8480eb
	master->logopt = master->default_logging;
Packit 8480eb
Packit 8480eb
	INIT_LIST_HEAD(&master->mounts);
Packit 8480eb
	INIT_LIST_HEAD(&master->completed);
Packit 8480eb
Packit 8480eb
	return master;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void master_add_amd_mount_section_mounts(struct master *master, time_t age)
Packit 8480eb
{
Packit 8480eb
	unsigned int m_logopt = master->logopt;
Packit 8480eb
	struct master_mapent *entry;
Packit 8480eb
	struct map_source *source;
Packit 8480eb
	unsigned int loglevel;
Packit 8480eb
	unsigned int logopt;
Packit 8480eb
	unsigned int flags;
Packit 8480eb
	char *argv[2];
Packit 8480eb
	char **paths;
Packit 8480eb
	int ret;
Packit 8480eb
	int i;
Packit 8480eb
Packit 8480eb
	loglevel = conf_amd_get_log_options();
Packit 8480eb
Packit 8480eb
	paths = conf_amd_get_mount_paths();
Packit 8480eb
	if (!paths)
Packit 8480eb
		return;
Packit 8480eb
Packit 8480eb
	i = 0;
Packit 8480eb
	while (paths[i]) {
Packit 8480eb
		const char *path = paths[i];
Packit 8480eb
		unsigned int ghost = 0;
Packit 8480eb
		time_t timeout;
Packit 8480eb
		char *type = NULL;
Packit 8480eb
		char *map = NULL;
Packit 8480eb
		char *opts;
Packit 8480eb
Packit 8480eb
		ret = master_partial_match_mapent(master, path);
Packit 8480eb
		if (ret) {
Packit 8480eb
			/* If this amd entry is already present in the
Packit 8480eb
			 * master map it's not a duplicate, don't issue
Packit 8480eb
			 * an error message.
Packit 8480eb
			 */
Packit 8480eb
			if (ret == 1)
Packit 8480eb
				goto next;
Packit 8480eb
			info(m_logopt,
Packit 8480eb
			     "amd section mount path conflict, %s ignored",
Packit 8480eb
			     path);
Packit 8480eb
			goto next;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		map = conf_amd_get_map_name(path);
Packit 8480eb
		if (!map) {
Packit 8480eb
			error(m_logopt,
Packit 8480eb
			      "failed to get map name for amd section mount %s",
Packit 8480eb
			      path);
Packit 8480eb
			goto next;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		entry = master_new_mapent(master, path, age);
Packit 8480eb
		if (!entry) {
Packit 8480eb
			error(m_logopt,
Packit 8480eb
			      "failed to allocate new amd section mount %s",
Packit 8480eb
			      path);
Packit 8480eb
			goto next;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		logopt = m_logopt;
Packit 8480eb
		if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
Packit 8480eb
			logopt = LOGOPT_DEBUG;
Packit 8480eb
		else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
Packit 8480eb
			logopt = LOGOPT_VERBOSE;
Packit 8480eb
Packit 8480eb
		/* It isn't possible to provide the fullybrowsable amd
Packit 8480eb
		 * browsing functionality within the autofs framework.
Packit 8480eb
		 * This flag will not be set if browsable_dirs = full
Packit 8480eb
		 * in the configuration or fullybrowsable is present as
Packit 8480eb
		 * an option.
Packit 8480eb
		 */
Packit 8480eb
		flags = conf_amd_get_flags(path);
Packit 8480eb
		if (flags & CONF_BROWSABLE_DIRS)
Packit 8480eb
			ghost = 1;
Packit 8480eb
Packit 8480eb
		ret = master_add_autofs_point(entry, logopt, 0, ghost, 0);
Packit 8480eb
		if (!ret) {
Packit 8480eb
			error(m_logopt, "failed to add autofs_point");
Packit 8480eb
			master_free_mapent(entry);
Packit 8480eb
			goto next;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		opts = conf_amd_get_map_options(path);
Packit 8480eb
		if (opts) {
Packit 8480eb
			/* autofs uses the equivalent of cache:=inc,sync
Packit 8480eb
			 * (except for file maps which use cache:=all,sync)
Packit 8480eb
			 * but if the map is large then it may be necessary
Packit 8480eb
			 * to read the whole map at startup even if browsing
Packit 8480eb
			 * is is not enabled, so look for cache:=all in the
Packit 8480eb
			 * map_options configuration entry.
Packit 8480eb
			 */
Packit 8480eb
			if (strstr(opts, "cache:=all"))
Packit 8480eb
				entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
Packit 8480eb
			free(opts);
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		type = conf_amd_get_map_type(path);
Packit 8480eb
		argv[0] = map;
Packit 8480eb
		argv[1] = NULL;
Packit 8480eb
Packit 8480eb
		source = master_add_map_source(entry, type, "amd",
Packit 8480eb
					       age, 1, (const char **) argv);
Packit 8480eb
		if (!source) {
Packit 8480eb
			error(m_logopt,
Packit 8480eb
			      "failed to add source for amd section mount %s",
Packit 8480eb
			      path);
Packit 8480eb
			master_free_mapent(entry);
Packit 8480eb
			goto next;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		timeout = conf_amd_get_dismount_interval(path);
Packit 8480eb
		set_exp_timeout(entry->ap, source, timeout);
Packit 8480eb
		source->master_line = 0;
Packit 8480eb
Packit 8480eb
		entry->age = age;
Packit 8480eb
		entry->current = NULL;
Packit 8480eb
Packit 8480eb
		master_add_mapent(master, entry);
Packit 8480eb
next:
Packit 8480eb
		if (type)
Packit 8480eb
			free(type);
Packit 8480eb
		if (map)
Packit 8480eb
			free(map);
Packit 8480eb
		i++;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	i = 0;
Packit 8480eb
	while (paths[i])
Packit 8480eb
		free(paths[i++]);
Packit 8480eb
	free(paths);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void wait_for_lookups_and_lock(struct master *master)
Packit 8480eb
{
Packit 8480eb
	struct list_head *p, *head;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
again:
Packit 8480eb
	master_mutex_lock();
Packit 8480eb
Packit 8480eb
	head = &master->mounts;
Packit 8480eb
	p = head->next;
Packit 8480eb
	while (p != head) {
Packit 8480eb
		struct master_mapent *this;
Packit 8480eb
Packit 8480eb
		this = list_entry(p, struct master_mapent, list);
Packit 8480eb
Packit 8480eb
		status = pthread_rwlock_trywrlock(&this->source_lock);
Packit 8480eb
		if (status) {
Packit 8480eb
			struct timespec t = { 0, 200000000 };
Packit 8480eb
			struct timespec r;
Packit 8480eb
Packit 8480eb
			master_mutex_unlock();
Packit 8480eb
Packit 8480eb
			while (nanosleep(&t, &r) == -1 && errno == EINTR)
Packit 8480eb
				memcpy(&t, &r, sizeof(struct timespec));
Packit 8480eb
Packit 8480eb
			goto again;
Packit 8480eb
		}
Packit 8480eb
		master_source_unlock(this);
Packit 8480eb
Packit 8480eb
		p = p->next;
Packit 8480eb
	}
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int master_read_master(struct master *master, time_t age, int readall)
Packit 8480eb
{
Packit 8480eb
	unsigned int logopt = master->logopt;
Packit 8480eb
	struct mapent_cache *nc;
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * We need to clear and re-populate the null map entry cache
Packit 8480eb
	 * before alowing anyone else to use it.
Packit 8480eb
	 */
Packit 8480eb
	wait_for_lookups_and_lock(master);
Packit 8480eb
	if (master->nc) {
Packit 8480eb
		cache_writelock(master->nc);
Packit 8480eb
		nc = master->nc;
Packit 8480eb
		cache_clean_null_cache(nc);
Packit 8480eb
	} else {
Packit 8480eb
		nc = cache_init_null_cache(master);
Packit 8480eb
		if (!nc) {
Packit 8480eb
			error(logopt,
Packit 8480eb
			      "failed to init null map cache for %s",
Packit 8480eb
			      master->name);
Packit 8480eb
			return 0;
Packit 8480eb
		}
Packit 8480eb
		cache_writelock(nc);
Packit 8480eb
		master->nc = nc;
Packit 8480eb
	}
Packit 8480eb
	master_init_scan();
Packit 8480eb
	lookup_nss_read_master(master, age);
Packit 8480eb
	cache_unlock(nc);
Packit 8480eb
	master_add_amd_mount_section_mounts(master, age);
Packit 8480eb
Packit 8480eb
	if (!master->read_fail)
Packit 8480eb
		master_mount_mounts(master, age, readall);
Packit 8480eb
	else {
Packit 8480eb
		master->read_fail = 0;
Packit 8480eb
		/* HUP signal sets readall == 1 only */
Packit 8480eb
		if (!readall) {
Packit 8480eb
			master_mutex_unlock();
Packit 8480eb
			return 0;
Packit 8480eb
		} else
Packit 8480eb
			master_mount_mounts(master, age, readall);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (list_empty(&master->mounts))
Packit 8480eb
		warn(logopt, "no mounts in table");
Packit 8480eb
Packit 8480eb
	master_mutex_unlock();
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int master_submount_list_empty(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	int res = 0;
Packit 8480eb
Packit 8480eb
	mounts_mutex_lock(ap);
Packit 8480eb
	if (list_empty(&ap->submounts))
Packit 8480eb
		res = 1;
Packit 8480eb
	mounts_mutex_unlock(ap);
Packit 8480eb
Packit 8480eb
	return res;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
Packit 8480eb
{
Packit 8480eb
	struct list_head *head, *p;
Packit 8480eb
	struct autofs_point *this = NULL;
Packit 8480eb
	int ret = 1;
Packit 8480eb
Packit 8480eb
	mounts_mutex_lock(ap);
Packit 8480eb
Packit 8480eb
	head = &ap->submounts;
Packit 8480eb
	p = head->prev;
Packit 8480eb
	while (p != head) {
Packit 8480eb
		this = list_entry(p, struct autofs_point, mounts);
Packit 8480eb
		p = p->prev;
Packit 8480eb
Packit 8480eb
		/* path not the same */
Packit 8480eb
		if (strcmp(this->path, path))
Packit 8480eb
			continue;
Packit 8480eb
Packit 8480eb
		if (!master_submount_list_empty(this)) {
Packit 8480eb
			char *this_path = strdup(this->path);
Packit 8480eb
			if (this_path) {
Packit 8480eb
				mounts_mutex_unlock(ap);
Packit 8480eb
				master_notify_submount(this, path, state);
Packit 8480eb
				mounts_mutex_lock(ap);
Packit 8480eb
				if (!__master_find_submount(ap, this_path)) {
Packit 8480eb
					free(this_path);
Packit 8480eb
					continue;
Packit 8480eb
				}
Packit 8480eb
				free(this_path);
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		/* Now we have found the submount we want to expire */
Packit 8480eb
Packit 8480eb
		st_mutex_lock();
Packit 8480eb
Packit 8480eb
		if (this->state == ST_SHUTDOWN) {
Packit 8480eb
			this = NULL;
Packit 8480eb
			st_mutex_unlock();
Packit 8480eb
			break;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		this->shutdown = ap->shutdown;
Packit 8480eb
Packit 8480eb
		__st_add_task(this, state);
Packit 8480eb
Packit 8480eb
		st_mutex_unlock();
Packit 8480eb
		mounts_mutex_unlock(ap);
Packit 8480eb
Packit 8480eb
		st_wait_task(this, state, 0);
Packit 8480eb
Packit 8480eb
		/*
Packit 8480eb
		 * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
Packit 8480eb
		 * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
Packit 8480eb
		 * to ST_READY.
Packit 8480eb
		 */
Packit 8480eb
		mounts_mutex_lock(ap);
Packit 8480eb
		st_mutex_lock();
Packit 8480eb
		while ((this = __master_find_submount(ap, path))) {
Packit 8480eb
			struct timespec t = { 0, 300000000 };
Packit 8480eb
			struct timespec r;
Packit 8480eb
Packit 8480eb
			if (this->state != ST_SHUTDOWN &&
Packit 8480eb
			    this->state != ST_SHUTDOWN_PENDING &&
Packit 8480eb
			    this->state != ST_SHUTDOWN_FORCE) {
Packit 8480eb
				ret = 0;
Packit 8480eb
				break;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			st_mutex_unlock();
Packit 8480eb
			mounts_mutex_unlock(ap);
Packit 8480eb
			while (nanosleep(&t, &r) == -1 && errno == EINTR)
Packit 8480eb
				memcpy(&t, &r, sizeof(struct timespec));
Packit 8480eb
			mounts_mutex_lock(ap);
Packit 8480eb
			st_mutex_lock();
Packit 8480eb
		}
Packit 8480eb
		st_mutex_unlock();
Packit 8480eb
		break;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	mounts_mutex_unlock(ap);
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void master_notify_state_change(struct master *master, int sig)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry;
Packit 8480eb
	struct autofs_point *ap;
Packit 8480eb
	struct list_head *p;
Packit 8480eb
	int cur_state;
Packit 8480eb
	unsigned int logopt;
Packit 8480eb
Packit 8480eb
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
Packit 8480eb
	master_mutex_lock();
Packit 8480eb
Packit 8480eb
	list_for_each(p, &master->mounts) {
Packit 8480eb
		enum states next = ST_INVAL;
Packit 8480eb
Packit 8480eb
		entry = list_entry(p, struct master_mapent, list);
Packit 8480eb
Packit 8480eb
		ap = entry->ap;
Packit 8480eb
		logopt = ap->logopt;
Packit 8480eb
Packit 8480eb
		st_mutex_lock();
Packit 8480eb
Packit 8480eb
		if (ap->state == ST_SHUTDOWN)
Packit 8480eb
			goto next;
Packit 8480eb
Packit 8480eb
		switch (sig) {
Packit 8480eb
		case SIGTERM:
Packit 8480eb
		case SIGINT:
Packit 8480eb
			if (ap->state != ST_SHUTDOWN_PENDING &&
Packit 8480eb
			    ap->state != ST_SHUTDOWN_FORCE) {
Packit 8480eb
				next = ST_SHUTDOWN_PENDING;
Packit 8480eb
				ap->shutdown = 1;
Packit 8480eb
				__st_add_task(ap, next);
Packit 8480eb
			}
Packit 8480eb
			break;
Packit 8480eb
#ifdef ENABLE_FORCED_SHUTDOWN
Packit 8480eb
		case SIGUSR2:
Packit 8480eb
			if (ap->state != ST_SHUTDOWN_FORCE &&
Packit 8480eb
			    ap->state != ST_SHUTDOWN_PENDING) {
Packit 8480eb
				next = ST_SHUTDOWN_FORCE;
Packit 8480eb
				ap->shutdown = 1;
Packit 8480eb
				__st_add_task(ap, next);
Packit 8480eb
			}
Packit 8480eb
			break;
Packit 8480eb
#endif
Packit 8480eb
		case SIGUSR1:
Packit 8480eb
			assert(ap->state == ST_READY);
Packit 8480eb
			next = ST_PRUNE;
Packit 8480eb
			__st_add_task(ap, next);
Packit 8480eb
			break;
Packit 8480eb
		}
Packit 8480eb
next:
Packit 8480eb
		if (next != ST_INVAL)
Packit 8480eb
			debug(logopt,
Packit 8480eb
			      "sig %d switching %s from %d to %d",
Packit 8480eb
			      sig, ap->path, ap->state, next);
Packit 8480eb
Packit 8480eb
		st_mutex_unlock();
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	master_mutex_unlock();
Packit 8480eb
	pthread_setcancelstate(cur_state, NULL);
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int master_do_mount(struct master_mapent *entry)
Packit 8480eb
{
Packit 8480eb
	struct startup_cond suc;
Packit 8480eb
	struct autofs_point *ap;
Packit 8480eb
	pthread_t thid;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	ap = entry->ap;
Packit 8480eb
Packit 8480eb
	if (handle_mounts_startup_cond_init(&suc)) {
Packit 8480eb
		crit(ap->logopt,
Packit 8480eb
		     "failed to init startup cond for mount %s", entry->path);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	suc.ap = ap;
Packit 8480eb
	suc.root = ap->path;
Packit 8480eb
	suc.done = 0;
Packit 8480eb
	suc.status = 0;
Packit 8480eb
Packit 8480eb
	debug(ap->logopt, "mounting %s", entry->path);
Packit 8480eb
Packit 8480eb
	status = pthread_create(&thid, &th_attr, handle_mounts, &suc);
Packit 8480eb
	if (status) {
Packit 8480eb
		crit(ap->logopt,
Packit 8480eb
		     "failed to create mount handler thread for %s",
Packit 8480eb
		     entry->path);
Packit 8480eb
		handle_mounts_startup_cond_destroy(&suc);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	while (!suc.done) {
Packit 8480eb
		status = pthread_cond_wait(&suc.cond, &suc.mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (suc.status) {
Packit 8480eb
		error(ap->logopt, "failed to startup mount");
Packit 8480eb
		handle_mounts_startup_cond_destroy(&suc);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
	entry->thid = thid;
Packit 8480eb
Packit 8480eb
	handle_mounts_startup_cond_destroy(&suc);
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void check_update_map_sources(struct master_mapent *entry, int readall)
Packit 8480eb
{
Packit 8480eb
	struct map_source *source, *last;
Packit 8480eb
	struct autofs_point *ap;
Packit 8480eb
	int map_stale = 0;
Packit 8480eb
Packit 8480eb
	if (readall)
Packit 8480eb
		map_stale = 1;
Packit 8480eb
Packit 8480eb
	ap = entry->ap;
Packit 8480eb
Packit 8480eb
	master_source_writelock(entry);
Packit 8480eb
Packit 8480eb
	last = NULL;
Packit 8480eb
	source = entry->maps;
Packit 8480eb
	while (source) {
Packit 8480eb
		if (readall)
Packit 8480eb
			source->stale = 1;
Packit 8480eb
Packit 8480eb
		/*
Packit 8480eb
		 * If a map source is no longer valid and all it's
Packit 8480eb
		 * entries have expired away we can get rid of it.
Packit 8480eb
		 */
Packit 8480eb
		if (entry->age > source->age) {
Packit 8480eb
			struct mapent *me;
Packit 8480eb
			cache_readlock(source->mc);
Packit 8480eb
			me = cache_lookup_first(source->mc);
Packit 8480eb
			if (!me) {
Packit 8480eb
				struct map_source *next = source->next;
Packit 8480eb
Packit 8480eb
				cache_unlock(source->mc);
Packit 8480eb
Packit 8480eb
				if (!last)
Packit 8480eb
					entry->maps = next;
Packit 8480eb
				else
Packit 8480eb
					last->next = next;
Packit 8480eb
Packit 8480eb
				if (entry->maps == source)
Packit 8480eb
					entry->maps = next;
Packit 8480eb
Packit 8480eb
				master_free_map_source(source, 1);
Packit 8480eb
Packit 8480eb
				source = next;
Packit 8480eb
				continue;
Packit 8480eb
			} else {
Packit 8480eb
				source->stale = 1;
Packit 8480eb
				map_stale = 1;
Packit 8480eb
			}
Packit 8480eb
			cache_unlock(source->mc);
Packit 8480eb
		}
Packit 8480eb
		last = source;
Packit 8480eb
		source = source->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	master_source_unlock(entry);
Packit 8480eb
Packit 8480eb
	/* The map sources have changed */
Packit 8480eb
	if (map_stale)
Packit 8480eb
		st_add_task(ap, ST_READMAP);
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int master_mount_mounts(struct master *master, time_t age, int readall)
Packit 8480eb
{
Packit 8480eb
	struct mapent_cache *nc = master->nc;
Packit 8480eb
	struct list_head *p, *head;
Packit 8480eb
	int cur_state;
Packit 8480eb
Packit 8480eb
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
Packit 8480eb
Packit 8480eb
	head = &master->mounts;
Packit 8480eb
	p = head->next;
Packit 8480eb
	while (p != head) {
Packit 8480eb
		struct master_mapent *this;
Packit 8480eb
		struct autofs_point *ap;
Packit 8480eb
		struct mapent *ne, *nested;
Packit 8480eb
		struct stat st;
Packit 8480eb
		int state_pipe, save_errno;
Packit 8480eb
		int ret;
Packit 8480eb
Packit 8480eb
		this = list_entry(p, struct master_mapent, list);
Packit 8480eb
		p = p->next;
Packit 8480eb
Packit 8480eb
		ap = this->ap;
Packit 8480eb
Packit 8480eb
		/* A master map entry has gone away */
Packit 8480eb
		if (this->age < age) {
Packit 8480eb
			st_add_task(ap, ST_SHUTDOWN_PENDING);
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		cache_readlock(nc);
Packit 8480eb
		ne = cache_lookup_distinct(nc, this->path);
Packit 8480eb
		/*
Packit 8480eb
		 * If this path matched a nulled entry the master map entry
Packit 8480eb
		 * must be an indirect mount so the master map entry line
Packit 8480eb
		 * number may be obtained from this->maps.
Packit 8480eb
		 */
Packit 8480eb
		if (ne) {
Packit 8480eb
			int lineno = ne->age;
Packit 8480eb
			cache_unlock(nc);
Packit 8480eb
Packit 8480eb
			/* null entry appears after map entry */
Packit 8480eb
			if (this->maps->master_line < lineno) {
Packit 8480eb
				warn(ap->logopt,
Packit 8480eb
				     "ignoring null entry that appears after "
Packit 8480eb
				     "existing entry for %s", this->path);
Packit 8480eb
				goto cont;
Packit 8480eb
			}
Packit 8480eb
			if (ap->state != ST_INIT) {
Packit 8480eb
				st_add_task(ap, ST_SHUTDOWN_PENDING);
Packit 8480eb
				continue;
Packit 8480eb
			}
Packit 8480eb
			/*
Packit 8480eb
			 * The map entry hasn't been started yet and we've
Packit 8480eb
			 * seen a preceeding null map entry for it so just
Packit 8480eb
			 * delete it from the master map entry list so it
Packit 8480eb
			 * doesn't get in the road.
Packit 8480eb
			 */
Packit 8480eb
			list_del_init(&this->list);
Packit 8480eb
			master_free_mapent_sources(ap->entry, 1);
Packit 8480eb
			master_free_mapent(ap->entry);
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
		nested = cache_partial_match(nc, this->path);
Packit 8480eb
		if (nested) {
Packit 8480eb
			error(ap->logopt,
Packit 8480eb
			     "removing invalid nested null entry %s",
Packit 8480eb
			     nested->key);
Packit 8480eb
			nested = cache_partial_match(nc, this->path);
Packit 8480eb
			if (nested)
Packit 8480eb
				cache_delete(nc, nested->key);
Packit 8480eb
		}
Packit 8480eb
		cache_unlock(nc);
Packit 8480eb
cont:
Packit 8480eb
		st_mutex_lock();
Packit 8480eb
Packit 8480eb
		state_pipe = this->ap->state_pipe[1];
Packit 8480eb
Packit 8480eb
		/* No pipe so mount is needed */
Packit 8480eb
		ret = fstat(state_pipe, &st);
Packit 8480eb
		save_errno = errno;
Packit 8480eb
Packit 8480eb
		st_mutex_unlock();
Packit 8480eb
Packit 8480eb
		if (!ret)
Packit 8480eb
			check_update_map_sources(this, readall);
Packit 8480eb
		else if (ret == -1 && save_errno == EBADF) {
Packit 8480eb
			if (!master_do_mount(this)) {
Packit 8480eb
				list_del_init(&this->list);
Packit 8480eb
				master_free_mapent_sources(ap->entry, 1);
Packit 8480eb
				master_free_mapent(ap->entry);
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	pthread_setcancelstate(cur_state, NULL);
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* The nss source instances end up in reverse order. */
Packit 8480eb
static void list_source_instances(struct map_source *source, struct map_source *instance)
Packit 8480eb
{
Packit 8480eb
	if (!source || !instance) {
Packit 8480eb
		printf("none");
Packit 8480eb
		return;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (instance->next)
Packit 8480eb
		list_source_instances(source, instance->next);
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * For convienience we map nss instance type "files" to "file".
Packit 8480eb
	 * Check for that and report corrected instance type.
Packit 8480eb
	 */
Packit 8480eb
	if (strcmp(instance->type, "file"))
Packit 8480eb
		printf("%s ", instance->type);
Packit 8480eb
	else {
Packit 8480eb
		if (source->argv && *(source->argv[0]) != '/')
Packit 8480eb
			printf("files ");
Packit 8480eb
		else
Packit 8480eb
			printf("%s ", instance->type);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void print_map_info(struct map_source *source)
Packit 8480eb
{
Packit 8480eb
	int argc = source->argc;
Packit 8480eb
	int i, multi, map_num;
Packit 8480eb
Packit 8480eb
	multi = (source->type && !strcmp(source->type, "multi"));
Packit 8480eb
	map_num = 1;
Packit 8480eb
	for (i = 0; i < argc; i++) {
Packit 8480eb
		if (source->argv[i] && *source->argv[i] != '-') {
Packit 8480eb
			if (!multi)
Packit 8480eb
				printf("  map: %s\n", source->argv[i]);
Packit 8480eb
			else
Packit 8480eb
				printf("  map[%i]: %s\n", map_num, source->argv[i]);
Packit 8480eb
			i++;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (i >= argc)
Packit 8480eb
			return;
Packit 8480eb
Packit 8480eb
		if (!strcmp(source->argv[i], "--"))
Packit 8480eb
			continue;
Packit 8480eb
Packit 8480eb
		if (source->argv[i]) {
Packit 8480eb
			int need_newline = 0;
Packit 8480eb
			int j;
Packit 8480eb
Packit 8480eb
			if (!multi)
Packit 8480eb
				printf("  arguments:");
Packit 8480eb
			else
Packit 8480eb
				printf("  arguments[%i]:", map_num);
Packit 8480eb
Packit 8480eb
			for (j = i; j < source->argc; j++) {
Packit 8480eb
				if (!strcmp(source->argv[j], "--"))
Packit 8480eb
					break;
Packit 8480eb
				printf(" %s", source->argv[j]);
Packit 8480eb
				i++;
Packit 8480eb
				need_newline = 1;
Packit 8480eb
			}
Packit 8480eb
			if (need_newline)
Packit 8480eb
				printf("\n");
Packit 8480eb
		}
Packit 8480eb
		if (multi)
Packit 8480eb
			map_num++;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int match_type(const char *source, const char *type)
Packit 8480eb
{
Packit 8480eb
	if (!strcmp(source, type))
Packit 8480eb
		return 1;
Packit 8480eb
	/* Sources file and files are synonymous */
Packit 8480eb
	if (!strncmp(source, type, 4) && (strlen(source) <= 5))
Packit 8480eb
		return 1;
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static char *get_map_name(const char *string)
Packit 8480eb
{
Packit 8480eb
	char *name, *tmp;
Packit 8480eb
	char *start, *end, *base;
Packit 8480eb
Packit 8480eb
	tmp = strdup(string);
Packit 8480eb
	if (!tmp) {
Packit 8480eb
		printf("error: allocation failure: %s\n", strerror(errno));
Packit 8480eb
		return NULL;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	base = basename(tmp);
Packit 8480eb
	end = strchr(base, ',');
Packit 8480eb
	if (end)
Packit 8480eb
		*end = '\0';
Packit 8480eb
	start = strchr(tmp, '=');
Packit 8480eb
	if (start)
Packit 8480eb
		start++;
Packit 8480eb
	else {
Packit 8480eb
		char *colon = strrchr(base, ':');
Packit 8480eb
		if (colon)
Packit 8480eb
			start = ++colon;
Packit 8480eb
		else
Packit 8480eb
			start = base;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	name = strdup(start);
Packit 8480eb
	if (!name)
Packit 8480eb
		printf("error: allocation failure: %s\n", strerror(errno));
Packit 8480eb
	free(tmp);
Packit 8480eb
Packit 8480eb
	return name;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int match_name(struct map_source *source, const char *name)
Packit 8480eb
{
Packit 8480eb
	int argc = source->argc;
Packit 8480eb
	int ret = 0;
Packit 8480eb
	int i;
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * This can't work for old style "multi" type sources since
Packit 8480eb
	 * there's no way to know from which map the cache entry came
Packit 8480eb
	 * from and duplicate entries are ignored at map read time.
Packit 8480eb
	 * All we can really do is list all the entries for the given
Packit 8480eb
	 * multi map if one of its map names matches.
Packit 8480eb
	 */
Packit 8480eb
	for (i = 0; i < argc; i++) {
Packit 8480eb
		if (i == 0 || !strcmp(source->argv[i], "--")) {
Packit 8480eb
			if (i != 0) {
Packit 8480eb
				i++;
Packit 8480eb
				if (i >= argc)
Packit 8480eb
					break;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			if (source->argv[i] && *source->argv[i] != '-') {
Packit 8480eb
				char *map = get_map_name(source->argv[i]);
Packit 8480eb
				if (!map)
Packit 8480eb
					break;
Packit 8480eb
				if (!strcmp(map, name)) {
Packit 8480eb
					ret = 1;
Packit 8480eb
					free(map);
Packit 8480eb
					break;
Packit 8480eb
				}
Packit 8480eb
				free(map);
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int dump_map(struct master *master, const char *type, const char *name)
Packit 8480eb
{
Packit 8480eb
	struct list_head *p, *head;
Packit 8480eb
Packit 8480eb
	if (list_empty(&master->mounts)) {
Packit 8480eb
		printf("no master map entries found\n");
Packit 8480eb
		return 1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	head = &master->mounts;
Packit 8480eb
	p = head->next;
Packit 8480eb
	while (p != head) {
Packit 8480eb
		struct map_source *source;
Packit 8480eb
		struct master_mapent *this;
Packit 8480eb
		struct autofs_point *ap;
Packit 8480eb
		time_t now = monotonic_time(NULL);
Packit 8480eb
Packit 8480eb
		this = list_entry(p, struct master_mapent, list);
Packit 8480eb
		p = p->next;
Packit 8480eb
Packit 8480eb
		ap = this->ap;
Packit 8480eb
Packit 8480eb
		/*
Packit 8480eb
		 * Ensure we actually read indirect map entries so we can
Packit 8480eb
		 * list them. The map reads won't read any indirect map
Packit 8480eb
		 * entries (other than those in a file map) unless the
Packit 8480eb
		 * browse option is set.
Packit 8480eb
		 */
Packit 8480eb
		if (ap->type == LKP_INDIRECT)
Packit 8480eb
			ap->flags |= MOUNT_FLAG_GHOST;
Packit 8480eb
Packit 8480eb
		/* Read the map content into the cache */
Packit 8480eb
		if (lookup_nss_read_map(ap, NULL, now))
Packit 8480eb
			lookup_prune_cache(ap, now);
Packit 8480eb
		else {
Packit 8480eb
			printf("failed to read map\n");
Packit 8480eb
			lookup_close_lookup(ap);
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (!this->maps) {
Packit 8480eb
			printf("no map sources found for %s\n", ap->path);
Packit 8480eb
			lookup_close_lookup(ap);
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		source = this->maps;
Packit 8480eb
		while (source) {
Packit 8480eb
			struct map_source *instance;
Packit 8480eb
			struct mapent *me;
Packit 8480eb
Packit 8480eb
			instance = NULL;
Packit 8480eb
			if (source->type) {
Packit 8480eb
				if (!match_type(source->type, type)) {
Packit 8480eb
					source = source->next;
Packit 8480eb
					continue;
Packit 8480eb
				}
Packit 8480eb
				if (!match_name(source, name)) {
Packit 8480eb
					source = source->next;
Packit 8480eb
					continue;
Packit 8480eb
				}
Packit 8480eb
				instance = source;
Packit 8480eb
			} else {
Packit 8480eb
				struct map_source *map;
Packit 8480eb
Packit 8480eb
				map = source->instance;
Packit 8480eb
				while (map) {
Packit 8480eb
					if (!match_type(map->type, type)) {
Packit 8480eb
						map = map->next;
Packit 8480eb
						continue;
Packit 8480eb
					}
Packit 8480eb
					if (!match_name(map, name)) {
Packit 8480eb
						map = map->next;
Packit 8480eb
						continue;
Packit 8480eb
					}
Packit 8480eb
					instance = map;
Packit 8480eb
					break;
Packit 8480eb
				}
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			if (!instance) {
Packit 8480eb
				source = source->next;
Packit 8480eb
				lookup_close_lookup(ap);
Packit 8480eb
				continue;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			me = cache_lookup_first(source->mc);
Packit 8480eb
			if (!me)
Packit 8480eb
				printf("no keys found in map\n");
Packit 8480eb
			else {
Packit 8480eb
				do {
Packit 8480eb
					if (me->source == instance)
Packit 8480eb
						printf("%s\t%s\n", me->key, me->mapent);
Packit 8480eb
				} while ((me = cache_lookup_next(source->mc, me)));
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			lookup_close_lookup(ap);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		lookup_close_lookup(ap);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int master_show_mounts(struct master *master)
Packit 8480eb
{
Packit 8480eb
	struct list_head *p, *head;
Packit 8480eb
Packit 8480eb
	printf("\nautofs dump map information\n"
Packit 8480eb
		 "===========================\n\n");
Packit 8480eb
Packit 8480eb
	printf("global options: ");
Packit 8480eb
	if (!global_options)
Packit 8480eb
		printf("none configured\n");
Packit 8480eb
	else {
Packit 8480eb
		printf("%s\n", global_options);
Packit 8480eb
		unsigned int append_options = defaults_get_append_options();
Packit 8480eb
		const char *append = append_options ? "will" : "will not";
Packit 8480eb
		printf("global options %s be appended to map entries\n", append);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (list_empty(&master->mounts)) {
Packit 8480eb
		printf("no master map entries found\n\n");
Packit 8480eb
		return 1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	head = &master->mounts;
Packit 8480eb
	p = head->next;
Packit 8480eb
	while (p != head) {
Packit 8480eb
		struct map_source *source;
Packit 8480eb
		struct master_mapent *this;
Packit 8480eb
		struct autofs_point *ap;
Packit 8480eb
		time_t now = monotonic_time(NULL);
Packit 8480eb
		unsigned int count = 0;
Packit 8480eb
Packit 8480eb
		this = list_entry(p, struct master_mapent, list);
Packit 8480eb
		p = p->next;
Packit 8480eb
Packit 8480eb
		ap = this->ap;
Packit 8480eb
Packit 8480eb
		printf("\nMount point: %s\n", ap->path);
Packit 8480eb
Packit 8480eb
		printf("\nsource(s):\n");
Packit 8480eb
Packit 8480eb
		/*
Packit 8480eb
		 * Ensure we actually read indirect map entries so we can
Packit 8480eb
		 * list them. The map reads won't read any indirect map
Packit 8480eb
		 * entries (other than those in a file map) unless the
Packit 8480eb
		 * browse option is set.
Packit 8480eb
		 */
Packit 8480eb
		if (ap->type == LKP_INDIRECT)
Packit 8480eb
			ap->flags |= MOUNT_FLAG_GHOST;
Packit 8480eb
Packit 8480eb
		/* Read the map content into the cache */
Packit 8480eb
		if (lookup_nss_read_map(ap, NULL, now))
Packit 8480eb
			lookup_prune_cache(ap, now);
Packit 8480eb
		else {
Packit 8480eb
			printf("  failed to read map\n\n");
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (!this->maps) {
Packit 8480eb
			printf("  no map sources found\n\n");
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		source = this->maps;
Packit 8480eb
		while (source) {
Packit 8480eb
			struct mapent *me;
Packit 8480eb
Packit 8480eb
			if (source->type)
Packit 8480eb
				printf("\n  type: %s\n", source->type);
Packit 8480eb
			else {
Packit 8480eb
				printf("\n  instance type(s): ");
Packit 8480eb
				list_source_instances(source, source->instance);
Packit 8480eb
				printf("\n");
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			if (source->argc >= 1) {
Packit 8480eb
				print_map_info(source);
Packit 8480eb
				if (count && ap->type == LKP_INDIRECT)
Packit 8480eb
					printf("  duplicate indirect map entry"
Packit 8480eb
					       " will be ignored at run time\n");
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			printf("\n");
Packit 8480eb
Packit 8480eb
			me = cache_lookup_first(source->mc);
Packit 8480eb
			if (!me)
Packit 8480eb
				printf("  no keys found in map\n");
Packit 8480eb
			else {
Packit 8480eb
				do {
Packit 8480eb
					printf("  %s | %s\n", me->key, me->mapent);
Packit 8480eb
				} while ((me = cache_lookup_next(source->mc, me)));
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			count++;
Packit 8480eb
Packit 8480eb
			source = source->next;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		lookup_close_lookup(ap);
Packit 8480eb
Packit 8480eb
		printf("\n");
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int master_list_empty(struct master *master)
Packit 8480eb
{
Packit 8480eb
	int res = 0;
Packit 8480eb
Packit 8480eb
	master_mutex_lock();
Packit 8480eb
	if (list_empty(&master->mounts))
Packit 8480eb
		res = 1;
Packit 8480eb
	master_mutex_unlock();
Packit 8480eb
Packit 8480eb
	return res;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int master_done(struct master *master)
Packit 8480eb
{
Packit 8480eb
	struct list_head *head, *p;
Packit 8480eb
	struct master_mapent *entry;
Packit 8480eb
	int res = 0;
Packit 8480eb
Packit 8480eb
	head = &master->completed;
Packit 8480eb
	p = head->next;
Packit 8480eb
	while (p != head) {
Packit 8480eb
		entry = list_entry(p, struct master_mapent, join);
Packit 8480eb
		p = p->next;
Packit 8480eb
		list_del(&entry->join);
Packit 8480eb
		pthread_join(entry->thid, NULL);
Packit 8480eb
		master_free_mapent_sources(entry, 1);
Packit 8480eb
		master_free_mapent(entry);
Packit 8480eb
	}
Packit 8480eb
	if (list_empty(&master->mounts))
Packit 8480eb
		res = 1;
Packit 8480eb
Packit 8480eb
	return res;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
unsigned int master_get_logopt(void)
Packit 8480eb
{
Packit 8480eb
	return master_list ? master_list->logopt : LOGOPT_NONE;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int master_kill(struct master *master)
Packit 8480eb
{
Packit 8480eb
	if (!list_empty(&master->mounts))
Packit 8480eb
		return 0;
Packit 8480eb
Packit 8480eb
	if (master->name)
Packit 8480eb
		free(master->name);
Packit 8480eb
Packit 8480eb
	cache_release_null_cache(master);
Packit 8480eb
	free(master);
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void dump_master(struct master *master)
Packit 8480eb
{
Packit 8480eb
	struct list_head *p, *head;
Packit 8480eb
Packit 8480eb
	head = &master->mounts;
Packit 8480eb
	list_for_each(p, head) {
Packit 8480eb
		struct master_mapent *this = list_entry(p, struct master_mapent, list);
Packit 8480eb
		logmsg("path %s", this->path);
Packit 8480eb
	}
Packit 8480eb
}