Blame daemon/lookup.c

Packit 8480eb
/* ----------------------------------------------------------------------- *
Packit 8480eb
 *   
Packit 8480eb
 *  lookup.c - API layer to implement nsswitch semantics for map reading
Packit 8480eb
 *		and mount lookups.
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 <stdio.h>
Packit 8480eb
#include <string.h>
Packit 8480eb
#include <sys/stat.h>
Packit 8480eb
#include "automount.h"
Packit 8480eb
#include "nsswitch.h"
Packit 8480eb
Packit 8480eb
static void nsslist_cleanup(void *arg)
Packit 8480eb
{
Packit 8480eb
	struct list_head *nsslist = (struct list_head *) arg;
Packit 8480eb
	if (!list_empty(nsslist))
Packit 8480eb
		free_sources(nsslist);
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int do_read_master(struct master *master, char *type, time_t age)
Packit 8480eb
{
Packit 8480eb
	struct lookup_mod *lookup;
Packit 8480eb
	const char *argv[2];
Packit 8480eb
	int argc;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	argc = 1;
Packit 8480eb
	argv[0] = master->name;
Packit 8480eb
	argv[1] = NULL;
Packit 8480eb
Packit 8480eb
	status = open_lookup(type, "", NULL, argc, argv, &lookup);
Packit 8480eb
	if (status != NSS_STATUS_SUCCESS)
Packit 8480eb
		return status;
Packit 8480eb
Packit 8480eb
	status = lookup->lookup_read_master(master, age, lookup->context);
Packit 8480eb
Packit 8480eb
	close_lookup(lookup);
Packit 8480eb
Packit 8480eb
	return status;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static char *find_map_path(struct autofs_point *ap, struct map_source *map)
Packit 8480eb
{
Packit 8480eb
	const char *mname = map->argv[0];
Packit 8480eb
	unsigned int mlen = strlen(mname);
Packit 8480eb
	char *tok, *ptr = NULL;
Packit 8480eb
	char *path = NULL;
Packit 8480eb
	char *search_path;
Packit 8480eb
	struct stat st;
Packit 8480eb
Packit Bot 44a4b2
	/* Absolute path, just return a copy */
Packit Bot 44a4b2
	if (mname[0] == '/')
Packit Bot 44a4b2
		return strdup(mname);
Packit Bot 44a4b2
Packit 8480eb
	/*
Packit 8480eb
	 * This is different to the way it is in amd.
Packit 8480eb
	 * autofs will always try to locate maps in AUTOFS_MAP_DIR
Packit 8480eb
	 * but amd has no default and will not find a file map that
Packit 8480eb
	 * isn't a full path when no search_path is configured, either
Packit 8480eb
	 * in the mount point or global configuration.
Packit 8480eb
	 */
Packit 8480eb
	search_path = strdup(AUTOFS_MAP_DIR);
Packit 8480eb
	if (map->flags & MAP_FLAG_FORMAT_AMD) {
Packit 8480eb
		struct autofs_point *pap = ap;
Packit 8480eb
		char *tmp;
Packit 8480eb
		/*
Packit 8480eb
		 * Make sure we get search_path from the root of the
Packit 8480eb
		 * mount tree, if one is present in the configuration.
Packit 8480eb
		 * Again different from amd, which ignores the submount
Packit 8480eb
		 * case.
Packit 8480eb
		 */
Packit 8480eb
		while (pap->parent)
Packit 8480eb
			pap = pap->parent;
Packit 8480eb
		tmp = conf_amd_get_search_path(pap->path);
Packit 8480eb
		if (tmp) {
Packit 8480eb
			if (search_path)
Packit 8480eb
				free(search_path);
Packit 8480eb
			search_path = tmp;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	if (!search_path)
Packit 8480eb
		return NULL;
Packit 8480eb
Packit 8480eb
	tok = strtok_r(search_path, ":", &ptr);
Packit 8480eb
	while (tok) {
Packit 8480eb
		char *this = malloc(strlen(tok) + mlen + 2);
Packit 8480eb
		if (!this) {
Packit 8480eb
			free(search_path);
Packit 8480eb
			return NULL;
Packit 8480eb
		}
Packit 8480eb
		strcpy(this, tok);
Packit 8480eb
		strcat(this, "/");
Packit 8480eb
		strcat(this, mname);
Packit 8480eb
		if (!stat(this, &st)) {
Packit 8480eb
			path = this;
Packit 8480eb
			break;
Packit 8480eb
		}
Packit 8480eb
		free(this);
Packit 8480eb
		tok = strtok_r(NULL, ":", &ptr);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	free(search_path);
Packit 8480eb
	return path;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int read_master_map(struct master *master, char *type, time_t age)
Packit 8480eb
{
Packit 8480eb
	unsigned int logopt = master->logopt;
Packit 8480eb
	char *path, *save_name;
Packit 8480eb
	int result;
Packit 8480eb
Packit 8480eb
	if (strcasecmp(type, "files")) {
Packit 8480eb
		return do_read_master(master, type, age);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* 
Packit 8480eb
	 * This is a special case as we need to append the
Packit 8480eb
	 * normal location to the map name.
Packit 8480eb
	 * note: It's invalid to specify a relative path.
Packit 8480eb
	 */
Packit 8480eb
Packit 8480eb
	if (strchr(master->name, '/')) {
Packit 8480eb
		error(logopt, "relative path invalid in files map name");
Packit 8480eb
		return NSS_STATUS_NOTFOUND;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	path = malloc(strlen(AUTOFS_MAP_DIR) + strlen(master->name) + 2);
Packit 8480eb
	if (!path)
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
Packit 8480eb
	strcpy(path, AUTOFS_MAP_DIR);
Packit 8480eb
	strcat(path, "/");
Packit 8480eb
	strcat(path, master->name);
Packit 8480eb
Packit 8480eb
	save_name = master->name;
Packit 8480eb
	master->name = path;
Packit 8480eb
Packit 8480eb
	result = do_read_master(master, type, age);
Packit 8480eb
Packit 8480eb
	master->name = save_name;
Packit 8480eb
	free(path);
Packit 8480eb
Packit 8480eb
	return result;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int lookup_nss_read_master(struct master *master, time_t age)
Packit 8480eb
{
Packit 8480eb
	unsigned int logopt = master->logopt;
Packit 8480eb
	struct list_head nsslist;
Packit 8480eb
	struct list_head *head, *p;
Packit 8480eb
	int result = NSS_STATUS_UNKNOWN;
Packit 8480eb
Packit 8480eb
	/* If it starts with a '/' it has to be a file or LDAP map */
Packit 8480eb
	if (*master->name == '/') {
Packit 8480eb
		if (*(master->name + 1) == '/') {
Packit 8480eb
			debug(logopt, "reading master ldap %s", master->name);
Packit 8480eb
			result = do_read_master(master, "ldap", age);
Packit 8480eb
		} else {
Packit 8480eb
			debug(logopt, "reading master file %s", master->name);
Packit 8480eb
			result = do_read_master(master, "file", age);
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (result == NSS_STATUS_UNAVAIL)
Packit 8480eb
			master->read_fail = 1;
Packit 8480eb
Packit 8480eb
		return result;
Packit 8480eb
	} else {
Packit 8480eb
		char *name = master->name;
Packit 8480eb
		char *tmp;
Packit 8480eb
Packit 8480eb
		/* Old style name specification will remain I think. */
Packit 8480eb
		tmp = strchr(name, ':');
Packit 8480eb
		if (tmp) {
Packit 8480eb
			char source[10];
Packit 8480eb
Packit 8480eb
			memset(source, 0, 10);
Packit 8480eb
			if ((!strncmp(name, "file", 4) &&
Packit 8480eb
				 (name[4] == ',' || name[4] == ':')) ||
Packit 8480eb
			    (!strncmp(name, "yp", 2) &&
Packit 8480eb
				 (name[2] == ',' || name[2] == ':')) ||
Packit 8480eb
			    (!strncmp(name, "nis", 3) &&
Packit 8480eb
				 (name[3] == ',' || name[3] == ':')) ||
Packit 8480eb
			    (!strncmp(name, "nisplus", 7) &&
Packit 8480eb
				 (name[7] == ',' || name[7] == ':')) ||
Packit 8480eb
			    (!strncmp(name, "ldap", 4) &&
Packit 8480eb
				 (name[4] == ',' || name[4] == ':')) ||
Packit 8480eb
			    (!strncmp(name, "ldaps", 5) &&
Packit 8480eb
				 (name[5] == ',' || name[5] == ':')) ||
Packit 8480eb
			    (!strncmp(name, "sss", 3) ||
Packit 8480eb
				 (name[3] == ',' || name[3] == ':')) ||
Packit 8480eb
			    (!strncmp(name, "dir", 3) &&
Packit 8480eb
				 (name[3] == ',' || name[3] == ':'))) {
Packit 8480eb
				strncpy(source, name, tmp - name);
Packit 8480eb
Packit 8480eb
				/*
Packit 8480eb
				 * If it's an ldap map leave the source in the
Packit 8480eb
				 * name so the lookup module can work out if
Packit 8480eb
				 * ldaps has been requested.
Packit 8480eb
				 */
Packit 8480eb
				if (strncmp(name, "ldap", 4)) {
Packit 8480eb
					master->name = tmp + 1;
Packit 8480eb
					debug(logopt, "reading master %s %s",
Packit 8480eb
					      source, master->name);
Packit 8480eb
				} else {
Packit 8480eb
					master->name = name;
Packit 8480eb
					debug(logopt, "reading master %s %s",
Packit 8480eb
					      source, tmp + 1);
Packit 8480eb
				}
Packit 8480eb
Packit 8480eb
				result = do_read_master(master, source, age);
Packit 8480eb
				master->name = name;
Packit 8480eb
Packit 8480eb
				if (result == NSS_STATUS_UNAVAIL)
Packit 8480eb
					master->read_fail = 1;
Packit 8480eb
Packit 8480eb
				return result;
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	INIT_LIST_HEAD(&nsslist);
Packit 8480eb
Packit 8480eb
	result = nsswitch_parse(&nsslist);
Packit 8480eb
	if (result) {
Packit 8480eb
		if (!list_empty(&nsslist))
Packit 8480eb
			free_sources(&nsslist);
Packit 8480eb
		error(logopt, "can't to read name service switch config.");
Packit 8480eb
		return NSS_STATUS_UNAVAIL;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* First one gets it */
Packit 8480eb
	result = NSS_STATUS_SUCCESS;
Packit 8480eb
	head = &nsslist;
Packit 8480eb
	list_for_each(p, head) {
Packit 8480eb
		struct nss_source *this;
Packit 8480eb
		int status;
Packit 8480eb
Packit 8480eb
		this = list_entry(p, struct nss_source, list);
Packit 8480eb
Packit 8480eb
		if (strncmp(this->source, "files", 5) &&
Packit 8480eb
		    strncmp(this->source, "nis", 3) &&
Packit 8480eb
		    strncmp(this->source, "nisplus", 7) &&
Packit 8480eb
		    strncmp(this->source, "ldap", 4) &&
Packit 8480eb
		    strncmp(this->source, "sss", 3))
Packit 8480eb
			continue;
Packit 8480eb
Packit 8480eb
		debug(logopt,
Packit 8480eb
		      "reading master %s %s", this->source, master->name);
Packit 8480eb
Packit 8480eb
		result = read_master_map(master, this->source, age);
Packit 8480eb
Packit 8480eb
		/*
Packit 8480eb
		 * If the name of the master map hasn't been explicitly
Packit 8480eb
		 * configured and we're not reading an included master map
Packit 8480eb
		 * then we're using auto.master as the default. Many setups
Packit 8480eb
		 * also use auto_master as the default master map so we
Packit 8480eb
		 * check for this map when auto.master isn't found.
Packit 8480eb
		 */
Packit 8480eb
		if (result != NSS_STATUS_SUCCESS &&
Packit 8480eb
		    !master->depth && !defaults_master_set()) {
Packit 8480eb
			char *tmp = strchr(master->name, '.');
Packit 8480eb
			if (tmp) {
Packit 8480eb
				debug(logopt,
Packit 8480eb
				      "%s not found, replacing '.' with '_'",
Packit 8480eb
				       master->name);
Packit 8480eb
				*tmp = '_';
Packit 8480eb
				result = read_master_map(master, this->source, age);
Packit 8480eb
				if (result != NSS_STATUS_SUCCESS)
Packit 8480eb
					*tmp = '.';
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		/* We've been instructed to move onto the next source */
Packit 8480eb
		if (result == NSS_STATUS_TRYAGAIN) {
Packit 8480eb
			result = NSS_STATUS_SUCCESS;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (result == NSS_STATUS_UNKNOWN ||
Packit 8480eb
		    result == NSS_STATUS_NOTFOUND) {
Packit 8480eb
			debug(logopt, "no map - continuing to next source");
Packit 8480eb
			result = NSS_STATUS_SUCCESS;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (result == NSS_STATUS_UNAVAIL)
Packit 8480eb
			master->read_fail = 1;
Packit 8480eb
Packit 8480eb
		status = check_nss_result(this, result);
Packit Bot c2600d
		if (status >= 0)
Packit Bot c2600d
			break;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (!list_empty(&nsslist))
Packit 8480eb
		free_sources(&nsslist);
Packit 8480eb
Packit 8480eb
	return result;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t age)
Packit 8480eb
{
Packit 8480eb
	struct lookup_mod *lookup;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	lookup = NULL;
Packit 8480eb
	master_source_writelock(ap->entry);
Packit 8480eb
	if (!map->lookup) {
Packit 8480eb
		status = open_lookup(map->type, "", map->format,
Packit 8480eb
				     map->argc, map->argv, &lookup);
Packit 8480eb
		if (status != NSS_STATUS_SUCCESS) {
Packit 8480eb
			master_source_unlock(ap->entry);
Packit 8480eb
			debug(ap->logopt,
Packit 8480eb
			      "lookup module %s open failed", map->type);
Packit 8480eb
			return status;
Packit 8480eb
		}
Packit 8480eb
		map->lookup = lookup;
Packit 8480eb
	} else {
Packit 8480eb
		lookup = map->lookup;
Packit 8480eb
		status = lookup->lookup_reinit(map->format,
Packit 8480eb
					       map->argc, map->argv,
Packit 8480eb
					       &lookup->context);
Packit 8480eb
		if (status)
Packit 8480eb
			warn(ap->logopt,
Packit 8480eb
			     "lookup module %s reinit failed", map->type);
Packit 8480eb
	}
Packit 8480eb
	master_source_unlock(ap->entry);
Packit 8480eb
Packit 8480eb
	if (!map->stale)
Packit 8480eb
		return NSS_STATUS_SUCCESS;
Packit 8480eb
Packit 8480eb
	master_source_current_wait(ap->entry);
Packit 8480eb
	ap->entry->current = map;
Packit 8480eb
Packit 8480eb
	status = lookup->lookup_read_map(ap, age, lookup->context);
Packit 8480eb
Packit 8480eb
	if (status != NSS_STATUS_SUCCESS)
Packit 8480eb
		map->stale = 0;
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * For maps that don't support enumeration return success
Packit 8480eb
	 * and do whatever we must to have autofs function with an
Packit 8480eb
	 * empty map entry cache.
Packit 8480eb
	 *
Packit 8480eb
	 * For indirect maps that use the browse option, when the
Packit 8480eb
	 * server is unavailable continue as best we can with
Packit 8480eb
	 * whatever we have in the cache, if anything.
Packit 8480eb
	 */
Packit 8480eb
	if (status == NSS_STATUS_UNKNOWN ||
Packit 8480eb
	   (ap->type == LKP_INDIRECT && status == NSS_STATUS_UNAVAIL))
Packit 8480eb
		return NSS_STATUS_SUCCESS;
Packit 8480eb
Packit 8480eb
	return status;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int read_file_source_instance(struct autofs_point *ap, struct map_source *map, time_t age)
Packit 8480eb
{
Packit 8480eb
	struct map_source *instance;
Packit 8480eb
	char src_file[] = "file";
Packit 8480eb
	char src_prog[] = "program";
Packit 8480eb
	struct stat st;
Packit 8480eb
	char *type, *format;
Packit Bot 44a4b2
	char *path;
Packit Bot 44a4b2
Packit Bot 44a4b2
	if (map->argc < 1) {
Packit Bot 44a4b2
		error(ap->logopt, "invalid arguments for autofs_point");
Packit Bot 44a4b2
		return NSS_STATUS_UNKNOWN;
Packit Bot 44a4b2
	}
Packit Service b713d9
Packit Bot 44a4b2
	path = find_map_path(ap, map);
Packit Bot 44a4b2
	if (!path)
Packit Bot 44a4b2
		return NSS_STATUS_UNKNOWN;
Packit Bot 44a4b2
Packit Bot 44a4b2
	if (stat(path, &st) == -1) {
Packit Bot 44a4b2
		warn(ap->logopt, "file map %s not found", path);
Packit Bot 44a4b2
		free(path);
Packit 8480eb
		return NSS_STATUS_NOTFOUND;
Packit 8480eb
	}
Packit 8480eb
Packit Bot 44a4b2
	if (!S_ISREG(st.st_mode)) {
Packit Bot 44a4b2
		free(path);
Packit 8480eb
		return NSS_STATUS_NOTFOUND;
Packit Bot 44a4b2
	}
Packit 8480eb
Packit 8480eb
	if (st.st_mode & __S_IEXEC)
Packit 8480eb
		type = src_prog;
Packit 8480eb
	else
Packit 8480eb
		type = src_file;
Packit 8480eb
Packit 8480eb
	format = map->format;
Packit 8480eb
Packit 8480eb
	instance = master_find_source_instance(map, type, format, 0, NULL);
Packit 8480eb
	if (!instance) {
Packit Bot 44a4b2
		const char **argv;
Packit Bot 44a4b2
		int argc;
Packit Bot 44a4b2
Packit Bot 44a4b2
		argc = map->argc;
Packit Bot 44a4b2
		argv = copy_argv(map->argc, map->argv);
Packit Bot 44a4b2
		if (!argv) {
Packit Bot 44a4b2
			error(ap->logopt, "failed to copy args");
Packit Bot 44a4b2
			free(path);
Packit Bot 44a4b2
			return NSS_STATUS_UNKNOWN;
Packit Bot 44a4b2
		}
Packit Bot 44a4b2
		if (argv[0])
Packit Bot 44a4b2
			free((char *) argv[0]);
Packit Bot 44a4b2
		argv[0] = path;
Packit Bot 44a4b2
		path = NULL;
Packit Bot 44a4b2
Packit 8480eb
		instance = master_add_source_instance(map, type, format, age, argc, argv);
Packit Bot 44a4b2
		free_argv(argc, argv);
Packit 8480eb
		if (!instance)
Packit 8480eb
			return NSS_STATUS_UNAVAIL;
Packit 8480eb
		instance->recurse = map->recurse;
Packit 8480eb
		instance->depth = map->depth;
Packit 8480eb
	}
Packit 8480eb
	instance->stale = map->stale;
Packit 8480eb
Packit Bot 44a4b2
	if (path)
Packit Bot 44a4b2
		free(path);
Packit Bot 44a4b2
Packit 8480eb
	return do_read_map(ap, instance, age);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int read_source_instance(struct autofs_point *ap, struct map_source *map, const char *type, time_t age)
Packit 8480eb
{
Packit 8480eb
	struct map_source *instance;
Packit 8480eb
	const char *format;
Packit 8480eb
Packit 8480eb
	format = map->format;
Packit 8480eb
Packit 8480eb
	instance = master_find_source_instance(map, type, format, 0, NULL);
Packit 8480eb
	if (!instance) {
Packit 8480eb
		int argc = map->argc;
Packit 8480eb
		const char **argv = map->argv;
Packit 8480eb
		instance = master_add_source_instance(map, type, format, age, argc, argv);
Packit 8480eb
		if (!instance)
Packit 8480eb
			return NSS_STATUS_UNAVAIL;
Packit 8480eb
		instance->recurse = map->recurse;
Packit 8480eb
		instance->depth = map->depth;
Packit 8480eb
	}
Packit 8480eb
	instance->stale = map->stale;
Packit 8480eb
Packit 8480eb
	return do_read_map(ap, instance, age);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void argv_cleanup(void *arg)
Packit 8480eb
{
Packit 8480eb
	struct map_source *tmap = (struct map_source *) arg;
Packit 8480eb
	/* path is freed in free_argv */
Packit 8480eb
	free_argv(tmap->argc, tmap->argv);
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int lookup_map_read_map(struct autofs_point *ap,
Packit 8480eb
			       struct map_source *map, time_t age)
Packit 8480eb
{
Packit 8480eb
	char *path;
Packit 8480eb
Packit 8480eb
	if (!map->argv[0]) {
Packit 8480eb
		if (!strcmp(map->type, "hosts"))
Packit 8480eb
			return do_read_map(ap, map, age);
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * This is only called when map->type != NULL.
Packit 8480eb
	 * We only need to look for a map if source type is
Packit 8480eb
	 * file and the map name doesn't begin with a "/".
Packit 8480eb
	 */
Packit 8480eb
	if (strncmp(map->type, "file", 4))
Packit 8480eb
		return do_read_map(ap, map, age);
Packit 8480eb
Packit 8480eb
	if (map->argv[0][0] == '/')
Packit 8480eb
		return do_read_map(ap, map, age);
Packit 8480eb
Packit 8480eb
	path = find_map_path(ap, map);
Packit 8480eb
	if (!path)
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
Packit 8480eb
	if (map->argc >= 1) {
Packit 8480eb
		if (map->argv[0])
Packit 8480eb
			free((char *) map->argv[0]);
Packit 8480eb
		map->argv[0] = path;
Packit 8480eb
	} else {
Packit 8480eb
		error(ap->logopt, "invalid arguments for autofs_point");
Packit 8480eb
		free(path);
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return do_read_map(ap, map, age);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static enum nsswitch_status read_map_source(struct nss_source *this,
Packit 8480eb
		struct autofs_point *ap, struct map_source *map, time_t age)
Packit 8480eb
{
Packit 8480eb
	if (strcasecmp(this->source, "files")) {
Packit 8480eb
		return read_source_instance(ap, map, this->source, age);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* 
Packit 8480eb
	 * This is a special case as we need to append the
Packit 8480eb
	 * normal location to the map name.
Packit 8480eb
	 * note: It's invalid to specify a relative path.
Packit 8480eb
	 */
Packit 8480eb
Packit 8480eb
	if (strchr(map->argv[0], '/')) {
Packit 8480eb
		error(ap->logopt, "relative path invalid in files map name");
Packit 8480eb
		return NSS_STATUS_NOTFOUND;
Packit 8480eb
	}
Packit 8480eb
Packit Bot 44a4b2
	return read_file_source_instance(ap, map, age);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time_t age)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry = ap->entry;
Packit 8480eb
	struct list_head nsslist;
Packit 8480eb
	struct list_head *head, *p;
Packit 8480eb
	struct nss_source *this;
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	enum nsswitch_status status;
Packit 8480eb
	unsigned int at_least_one = 0;
Packit 8480eb
	int result = 0;
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * For each map source (ie. each entry for the mount
Packit 8480eb
	 * point in the master map) do the nss lookup to
Packit 8480eb
	 * locate the map and read it.
Packit 8480eb
	 */
Packit 8480eb
	if (source)
Packit 8480eb
		map = source;
Packit 8480eb
	else
Packit 8480eb
		map = entry->maps;
Packit 8480eb
	while (map) {
Packit 8480eb
		/* Is map source up to date or no longer valid */
Packit 8480eb
		if (!map->stale || entry->age > map->age) {
Packit 8480eb
			map = map->next;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (map->type) {
Packit 8480eb
			if (!strncmp(map->type, "multi", 5))
Packit 8480eb
				debug(ap->logopt, "reading multi map");
Packit 8480eb
			else
Packit 8480eb
				debug(ap->logopt,
Packit 8480eb
				      "reading map %s %s",
Packit 8480eb
				       map->type, map->argv[0]);
Packit 8480eb
			result = lookup_map_read_map(ap, map, age);
Packit 8480eb
			map = map->next;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		/* If it starts with a '/' it has to be a file or LDAP map */
Packit 8480eb
		if (map->argv && *map->argv[0] == '/') {
Packit 8480eb
			if (*(map->argv[0] + 1) == '/') {
Packit 8480eb
				char *tmp = strdup("ldap");
Packit 8480eb
				if (!tmp) {
Packit 8480eb
					map = map->next;
Packit 8480eb
					continue;
Packit 8480eb
				}
Packit 8480eb
				map->type = tmp;
Packit 8480eb
				debug(ap->logopt,
Packit 8480eb
				      "reading map %s %s", tmp, map->argv[0]);
Packit 8480eb
				result = do_read_map(ap, map, age);
Packit 8480eb
			} else {
Packit 8480eb
				debug(ap->logopt,
Packit 8480eb
				      "reading map file %s", map->argv[0]);
Packit 8480eb
				result = read_file_source_instance(ap, map, age);
Packit 8480eb
			}
Packit 8480eb
			map = map->next;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		INIT_LIST_HEAD(&nsslist);
Packit 8480eb
Packit 8480eb
		pthread_cleanup_push(nsslist_cleanup, &nsslist);
Packit 8480eb
		status = nsswitch_parse(&nsslist);
Packit 8480eb
		pthread_cleanup_pop(0);
Packit 8480eb
		if (status) {
Packit 8480eb
			error(ap->logopt,
Packit 8480eb
			      "can't to read name service switch config.");
Packit 8480eb
			result = 1;
Packit 8480eb
			break;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		pthread_cleanup_push(nsslist_cleanup, &nsslist);
Packit 8480eb
		head = &nsslist;
Packit 8480eb
		list_for_each(p, head) {
Packit 8480eb
			this = list_entry(p, struct nss_source, list);
Packit 8480eb
Packit 8480eb
			if (map->flags & MAP_FLAG_FORMAT_AMD &&
Packit 8480eb
			    !strcmp(this->source, "sss")) {
Packit 8480eb
				warn(ap->logopt,
Packit 8480eb
				     "source sss is not available for amd maps.");
Packit 8480eb
				continue;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			debug(ap->logopt,
Packit 8480eb
			      "reading map %s %s", this->source, map->argv[0]);
Packit 8480eb
Packit 8480eb
			result = read_map_source(this, ap, map, age);
Packit 8480eb
			if (result == NSS_STATUS_UNKNOWN)
Packit 8480eb
				continue;
Packit 8480eb
Packit 8480eb
			/* Try to avoid updating the map cache if an instance
Packit 8480eb
			 * is unavailable */
Packit 8480eb
			if (result == NSS_STATUS_UNAVAIL)
Packit 8480eb
				map->stale = 0;
Packit 8480eb
Packit 8480eb
			if (result == NSS_STATUS_SUCCESS) {
Packit 8480eb
				at_least_one = 1;
Packit 8480eb
				result = NSS_STATUS_TRYAGAIN;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			status = check_nss_result(this, result);
Packit 8480eb
			if (status >= 0) {
Packit 8480eb
				map = NULL;
Packit 8480eb
				break;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			result = NSS_STATUS_SUCCESS;
Packit 8480eb
		}
Packit 8480eb
		pthread_cleanup_pop(1);
Packit 8480eb
Packit 8480eb
		if (!map)
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (!result || at_least_one)
Packit 8480eb
		return 1;
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static char *make_browse_path(unsigned int logopt,
Packit 8480eb
			      const char *root, const char *key,
Packit 8480eb
			      const char *prefix)
Packit 8480eb
{
Packit 8480eb
	unsigned int l_prefix;
Packit 8480eb
	unsigned int k_len, r_len;
Packit 8480eb
	char *k_start;
Packit 8480eb
	char *path;
Packit 8480eb
Packit 8480eb
	k_start = (char *) key;
Packit 8480eb
	k_len = strlen(key);
Packit 8480eb
	l_prefix = 0;
Packit 8480eb
Packit 8480eb
	if (prefix) {
Packit 8480eb
		l_prefix = strlen(prefix);
Packit 8480eb
Packit 8480eb
		if (l_prefix > k_len)
Packit 8480eb
			return NULL;
Packit 8480eb
Packit 8480eb
		/* If the prefix doesn't match the beginning
Packit 8480eb
		 * of the key this entry isn't a sub directory
Packit 8480eb
		 * at this level.
Packit 8480eb
		 */
Packit 8480eb
		if (strncmp(key, prefix, l_prefix))
Packit 8480eb
			return NULL;
Packit 8480eb
Packit 8480eb
		/* Directory entry starts following the prefix */
Packit 8480eb
		k_start += l_prefix;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* No remaining "/" allowed here */
Packit 8480eb
	if (strchr(k_start, '/'))
Packit 8480eb
		return NULL;
Packit 8480eb
Packit 8480eb
	r_len = strlen(root);
Packit 8480eb
Packit 8480eb
	if ((r_len + strlen(k_start)) > KEY_MAX_LEN)
Packit 8480eb
		return NULL;
Packit 8480eb
Packit 8480eb
	path = malloc(r_len + k_len + 2);
Packit 8480eb
	if (!path) {
Packit 8480eb
		warn(logopt, "failed to allocate full path");
Packit 8480eb
		return NULL;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	sprintf(path, "%s/%s", root, k_start);
Packit 8480eb
Packit 8480eb
	return path;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int lookup_ghost(struct autofs_point *ap, const char *root)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry = ap->entry;
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	struct mapent_cache *mc;
Packit 8480eb
	struct mapent *me;
Packit 8480eb
	char buf[MAX_ERR_BUF];
Packit 8480eb
	struct stat st;
Packit 8480eb
	char *fullpath;
Packit 8480eb
	int ret;
Packit 8480eb
Packit 8480eb
	if (!strcmp(ap->path, "/-"))
Packit 8480eb
		return LKP_FAIL | LKP_DIRECT;
Packit 8480eb
Packit 8480eb
	if (!(ap->flags & MOUNT_FLAG_GHOST))
Packit 8480eb
		return LKP_INDIRECT;
Packit 8480eb
Packit 8480eb
	pthread_cleanup_push(master_source_lock_cleanup, entry);
Packit 8480eb
	master_source_readlock(entry);
Packit 8480eb
	map = entry->maps;
Packit 8480eb
	while (map) {
Packit 8480eb
		/*
Packit 8480eb
		 * Only consider map sources that have been read since 
Packit 8480eb
		 * the map entry was last updated.
Packit 8480eb
		 */
Packit 8480eb
		if (entry->age > map->age) {
Packit 8480eb
			map = map->next;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		mc = map->mc;
Packit 8480eb
		pthread_cleanup_push(cache_lock_cleanup, mc);
Packit 8480eb
		cache_readlock(mc);
Packit 8480eb
		me = cache_enumerate(mc, NULL);
Packit 8480eb
		while (me) {
Packit 8480eb
			/*
Packit 8480eb
			 * Map entries that have been created in the cache
Packit 8480eb
			 * due to a negative lookup shouldn't have directories
Packit 8480eb
			 * created if they haven't already been created.
Packit 8480eb
			 */
Packit 8480eb
			if (!me->mapent)
Packit 8480eb
				goto next;
Packit 8480eb
Packit 8480eb
			/* Wildcard cannot be a browse directory and amd map
Packit 8480eb
			 * keys may end with the wildcard.
Packit 8480eb
			 */
Packit 8480eb
			if (strchr(me->key, '*'))
Packit 8480eb
				goto next;
Packit 8480eb
Packit 8480eb
			/* This will also take care of amd "/defaults" entry as
Packit 8480eb
			 * amd map keys are not allowd to start with "/"
Packit 8480eb
			 */
Packit 8480eb
			if (*me->key == '/') {
Packit 8480eb
				if (map->flags & MAP_FLAG_FORMAT_AMD)
Packit 8480eb
					goto next;
Packit 8480eb
Packit 8480eb
				/* It's a busy multi-mount - leave till next time */
Packit Bot 7bc25c
				if (IS_MM(me))
Packit 8480eb
					error(ap->logopt,
Packit 8480eb
					      "invalid key %s", me->key);
Packit 8480eb
				goto next;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			fullpath = make_browse_path(ap->logopt,
Packit 8480eb
						    root, me->key, ap->pref);
Packit 8480eb
			if (!fullpath)
Packit 8480eb
				goto next;
Packit 8480eb
Packit 8480eb
			ret = stat(fullpath, &st);
Packit 8480eb
			if (ret == -1 && errno != ENOENT) {
Packit 8480eb
				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
				warn(ap->logopt, "stat error %s", estr);
Packit 8480eb
				free(fullpath);
Packit 8480eb
				goto next;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			/* Directory already exists? */
Packit 8480eb
			if (!ret) {
Packit 8480eb
				free(fullpath);
Packit 8480eb
				goto next;
Packit 8480eb
			}
Packit 8480eb
Packit Bot bc4df2
			ret = mkdir_path(fullpath, mp_mode);
Packit 8480eb
			if (ret < 0 && errno != EEXIST) {
Packit 8480eb
				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
				warn(ap->logopt,
Packit 8480eb
				     "mkdir_path %s failed: %s", fullpath, estr);
Packit 8480eb
				free(fullpath);
Packit 8480eb
				goto next;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			if (stat(fullpath, &st) != -1) {
Packit 8480eb
				me->dev = st.st_dev;
Packit 8480eb
				me->ino = st.st_ino;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			free(fullpath);
Packit 8480eb
next:
Packit 8480eb
			me = cache_enumerate(mc, me);
Packit 8480eb
		}
Packit 8480eb
		pthread_cleanup_pop(1);
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
	pthread_cleanup_pop(1);
Packit 8480eb
Packit 8480eb
	return LKP_INDIRECT;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int do_lookup_mount(struct autofs_point *ap, struct map_source *map, const char *name, int name_len)
Packit 8480eb
{
Packit 8480eb
	struct lookup_mod *lookup;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	if (!map->lookup) {
Packit 8480eb
		status = open_lookup(map->type, "",
Packit 8480eb
				     map->format, map->argc, map->argv, &lookup);
Packit 8480eb
		if (status != NSS_STATUS_SUCCESS) {
Packit 8480eb
			debug(ap->logopt,
Packit 8480eb
			      "lookup module %s open failed", map->type);
Packit 8480eb
			return status;
Packit 8480eb
		}
Packit 8480eb
		map->lookup = lookup;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	lookup = map->lookup;
Packit 8480eb
Packit 8480eb
	master_source_current_wait(ap->entry);
Packit 8480eb
	ap->entry->current = map;
Packit 8480eb
Packit 8480eb
	status = lookup->lookup_mount(ap, name, name_len, lookup->context);
Packit 8480eb
Packit 8480eb
	return status;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int lookup_amd_instance(struct autofs_point *ap,
Packit 8480eb
			       struct map_source *map,
Packit 8480eb
			       const char *name, int name_len)
Packit 8480eb
{
Packit 8480eb
	struct map_source *instance;
Packit Bot 5cfc5d
	struct mnt_list *mnt;
Packit 8480eb
	const char *argv[2];
Packit 8480eb
	const char **pargv = NULL;
Packit 8480eb
	int argc = 0;
Packit 8480eb
	struct mapent *me;
Packit 8480eb
	char *m_key;
Packit 8480eb
Packit 8480eb
	me = cache_lookup_distinct(map->mc, name);
Packit Bot 7bc25c
	if (!me || !IS_MM(me)) {
Packit 8480eb
		error(ap->logopt, "expected multi mount entry not found");
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
	}
Packit 8480eb
Packit Bot c177e8
	m_key = malloc(ap->len + MM_ROOT(me)->len + 2);
Packit 8480eb
	if (!m_key) {
Packit 8480eb
		error(ap->logopt,
Packit 8480eb
		     "failed to allocate storage for search key");
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	strcpy(m_key, ap->path);
Packit 8480eb
	strcat(m_key, "/");
Packit Bot 7bc25c
	strcat(m_key, MM_ROOT(me)->key);
Packit Bot 5cfc5d
Packit Bot 5cfc5d
	mnt = mnts_find_amdmount(m_key);
Packit 8480eb
	free(m_key);
Packit 8480eb
Packit Bot 5cfc5d
	if (!mnt) {
Packit 8480eb
		error(ap->logopt, "expected amd mount entry not found");
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
	}
Packit 8480eb
Packit Bot 5cfc5d
	if (strcmp(mnt->amd_type, "host")) {
Packit Bot 5cfc5d
		error(ap->logopt, "unexpected map type %s", mnt->amd_type);
Packit Bot 5cfc5d
		mnts_put_mount(mnt);
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
	}
Packit 8480eb
Packit Bot 5cfc5d
	if (mnt->amd_opts && *mnt->amd_opts) {
Packit Bot 5cfc5d
		argv[0] = mnt->amd_opts;
Packit 8480eb
		argv[1] = NULL;
Packit 8480eb
		pargv = argv;
Packit 8480eb
		argc = 1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	instance = master_find_source_instance(map, "hosts", "sun", argc, pargv);
Packit 8480eb
	/* If this is an nss map instance it may have an amd host map sub instance */
Packit 8480eb
	if (!instance && map->instance) {
Packit 8480eb
		struct map_source *next = map->instance;
Packit 8480eb
		while (next) {
Packit 8480eb
			instance = master_find_source_instance(next,
Packit 8480eb
						"hosts", "sun", argc, pargv);
Packit 8480eb
			if (instance)
Packit 8480eb
				break;
Packit 8480eb
			next = next->next;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	if (!instance) {
Packit Bot 5cfc5d
		mnts_put_mount(mnt);
Packit 8480eb
		error(ap->logopt, "expected hosts map instance not found");
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
	}
Packit Bot 5cfc5d
	mnts_put_mount(mnt);
Packit 8480eb
Packit 8480eb
	return do_lookup_mount(ap, instance, name, name_len);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int lookup_name_file_source_instance(struct autofs_point *ap, struct map_source *map, const char *name, int name_len)
Packit 8480eb
{
Packit 8480eb
	struct map_source *instance;
Packit 8480eb
	char src_file[] = "file";
Packit 8480eb
	char src_prog[] = "program";
Packit 8480eb
	time_t age = monotonic_time(NULL);
Packit 8480eb
	struct stat st;
Packit 8480eb
	char *type, *format;
Packit Bot 44a4b2
	char *path;
Packit 8480eb
Packit 8480eb
	if (*name == '/' && map->flags & MAP_FLAG_FORMAT_AMD)
Packit 8480eb
		return lookup_amd_instance(ap, map, name, name_len);
Packit 8480eb
Packit Bot 44a4b2
	if (map->argc < 1) {
Packit Bot 44a4b2
		error(ap->logopt, "invalid arguments for autofs_point");
Packit Bot 44a4b2
		return NSS_STATUS_UNKNOWN;
Packit Bot 44a4b2
	}
Packit Bot 44a4b2
Packit Bot 44a4b2
	path = find_map_path(ap, map);
Packit Bot 44a4b2
	if (!path)
Packit Bot 44a4b2
		return NSS_STATUS_UNKNOWN;
Packit Bot 44a4b2
Packit Bot 44a4b2
	if (stat(path, &st) == -1) {
Packit 8480eb
		debug(ap->logopt, "file map not found");
Packit Bot 44a4b2
		free(path);
Packit 8480eb
		return NSS_STATUS_NOTFOUND;
Packit 8480eb
	}
Packit 8480eb
Packit Bot 44a4b2
	if (!S_ISREG(st.st_mode)) {
Packit Bot 44a4b2
		free(path);
Packit 8480eb
		return NSS_STATUS_NOTFOUND;
Packit Bot 44a4b2
	}
Packit 8480eb
Packit 8480eb
	if (st.st_mode & __S_IEXEC)
Packit 8480eb
		type = src_prog;
Packit 8480eb
	else
Packit 8480eb
		type = src_file;
Packit 8480eb
Packit 8480eb
	format = map->format;
Packit 8480eb
Packit 8480eb
	instance = master_find_source_instance(map, type, format, 0, NULL);
Packit 8480eb
	if (!instance) {
Packit Bot 44a4b2
		const char **argv;
Packit Bot 44a4b2
		int argc;
Packit Bot 44a4b2
Packit Bot 44a4b2
		argc = map->argc;
Packit Bot 44a4b2
		argv = copy_argv(map->argc, map->argv);
Packit Bot 44a4b2
		if (!argv) {
Packit Bot 44a4b2
			error(ap->logopt, "failed to copy args");
Packit Bot 44a4b2
			free(path);
Packit Bot 44a4b2
			return NSS_STATUS_UNKNOWN;
Packit Bot 44a4b2
		}
Packit Bot 44a4b2
		if (argv[0])
Packit Bot 44a4b2
			free((char *) argv[0]);
Packit Bot 44a4b2
		argv[0] = path;
Packit Bot 44a4b2
		path = NULL;
Packit Bot 44a4b2
Packit 8480eb
		instance = master_add_source_instance(map, type, format, age, argc, argv);
Packit Bot 44a4b2
		free_argv(argc, argv);
Packit 8480eb
		if (!instance)
Packit 8480eb
			return NSS_STATUS_NOTFOUND;
Packit 8480eb
		instance->recurse = map->recurse;
Packit 8480eb
		instance->depth = map->depth;
Packit 8480eb
	}
Packit 8480eb
Packit Bot 44a4b2
	if (path)
Packit Bot 44a4b2
		free(path);
Packit Bot 44a4b2
Packit 8480eb
	return do_lookup_mount(ap, instance, name, name_len);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int lookup_name_source_instance(struct autofs_point *ap, struct map_source *map, const char *type, const char *name, int name_len)
Packit 8480eb
{
Packit 8480eb
	struct map_source *instance;
Packit 8480eb
	const char *format;
Packit 8480eb
	time_t age = monotonic_time(NULL);
Packit 8480eb
Packit 8480eb
	if (*name == '/' && map->flags & MAP_FLAG_FORMAT_AMD)
Packit 8480eb
		return lookup_amd_instance(ap, map, name, name_len);
Packit 8480eb
Packit 8480eb
	format = map->format;
Packit 8480eb
Packit 8480eb
	instance = master_find_source_instance(map, type, format, 0, NULL);
Packit 8480eb
	if (!instance) {
Packit 8480eb
		int argc = map->argc;
Packit 8480eb
		const char **argv = map->argv;
Packit 8480eb
		instance = master_add_source_instance(map, type, format, age, argc, argv);
Packit 8480eb
		if (!instance)
Packit 8480eb
			return NSS_STATUS_NOTFOUND;
Packit 8480eb
		instance->recurse = map->recurse;
Packit 8480eb
		instance->depth = map->depth;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return do_lookup_mount(ap, instance, name, name_len);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int do_name_lookup_mount(struct autofs_point *ap,
Packit 8480eb
				struct map_source *map,
Packit 8480eb
				const char *name, int name_len)
Packit 8480eb
{
Packit 8480eb
	char *path;
Packit 8480eb
Packit 8480eb
	if (!map->argv[0]) {
Packit 8480eb
		if (!strcmp(map->type, "hosts"))
Packit 8480eb
			return do_lookup_mount(ap, map, name, name_len);
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (*name == '/' && map->flags & MAP_FLAG_FORMAT_AMD)
Packit 8480eb
		return lookup_amd_instance(ap, map, name, name_len);
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * This is only called when map->type != NULL.
Packit 8480eb
	 * We only need to look for a map if source type is
Packit 8480eb
	 * file and the map name doesn't begin with a "/".
Packit 8480eb
	 */
Packit 8480eb
	if (strncmp(map->type, "file", 4))
Packit 8480eb
		return do_lookup_mount(ap, map, name, name_len);
Packit 8480eb
Packit 8480eb
	if (map->argv[0][0] == '/')
Packit 8480eb
		return do_lookup_mount(ap, map, name, name_len);
Packit 8480eb
Packit 8480eb
	path = find_map_path(ap, map);
Packit 8480eb
	if (!path)
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
Packit 8480eb
	if (map->argc >= 1) {
Packit 8480eb
		if (map->argv[0])
Packit 8480eb
			free((char *) map->argv[0]);
Packit 8480eb
		map->argv[0] = path;
Packit 8480eb
	} else {
Packit 8480eb
		error(ap->logopt, "invalid arguments for autofs_point");
Packit 8480eb
		free(path);
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return do_lookup_mount(ap, map, name, name_len);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static enum nsswitch_status lookup_map_name(struct nss_source *this,
Packit 8480eb
			struct autofs_point *ap, struct map_source *map,
Packit 8480eb
			const char *name, int name_len)
Packit 8480eb
{
Packit 8480eb
	if (strcasecmp(this->source, "files"))
Packit 8480eb
		return lookup_name_source_instance(ap, map,
Packit 8480eb
					this->source, name, name_len);
Packit 8480eb
Packit 8480eb
	/* 
Packit 8480eb
	 * autofs build-in map for nsswitch "files" is "file".
Packit 8480eb
	 * This is a special case as we need to append the
Packit 8480eb
	 * normal location to the map name.
Packit 8480eb
	 * note: we consider it invalid to specify a relative
Packit 8480eb
	 *       path.
Packit 8480eb
	 */
Packit 8480eb
	if (strchr(map->argv[0], '/')) {
Packit 8480eb
		error(ap->logopt, "relative path invalid in files map name");
Packit 8480eb
		return NSS_STATUS_NOTFOUND;
Packit 8480eb
	}
Packit 8480eb
Packit Bot 44a4b2
	return lookup_name_file_source_instance(ap, map, name, name_len);
Packit Service 5a0782
}
Packit Service 5a0782
Packit Bot 7679ed
static struct map_source *lookup_get_map_source(struct master_mapent *entry)
Packit Bot 7679ed
{
Packit Bot 7679ed
	struct map_source *map = entry->maps;
Packit Bot 7679ed
	struct stat st;
Packit Bot 7679ed
	char *type;
Packit Bot 7679ed
Packit Bot 7679ed
	if (map->type || *map->argv[0] != '/')
Packit Bot 7679ed
		return map;
Packit Bot 7679ed
Packit Bot 7679ed
	if (*(map->argv[0] + 1) == '/')
Packit Bot 7679ed
		return map;
Packit Bot 7679ed
Packit Bot 7679ed
	if (stat(map->argv[0], &st) == -1)
Packit Bot 7679ed
		return NULL;
Packit Bot 7679ed
Packit Bot 7679ed
	if (!S_ISREG(st.st_mode))
Packit Bot 7679ed
		return NULL;
Packit Bot 7679ed
Packit Bot 7679ed
	if (st.st_mode & __S_IEXEC)
Packit Bot 7679ed
		type = "program";
Packit Bot 7679ed
	else
Packit Bot 7679ed
		type = "file";
Packit Bot 7679ed
Packit Bot 7679ed
	/* This is a file source with a path starting with "/".
Packit Bot 7679ed
	 * But file maps can be either plain text or executable
Packit Bot 7679ed
	 * so they use a map instance and the actual map source
Packit Bot 7679ed
	 * remains untouched.
Packit Bot 7679ed
	 */
Packit Bot 7679ed
	return master_find_source_instance(map, type, map->format, 0, NULL);
Packit Bot 7679ed
}
Packit Bot 7679ed
Packit 8480eb
static void update_negative_cache(struct autofs_point *ap, struct map_source *source, const char *name)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry = ap->entry;
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	struct mapent *me;
Packit 8480eb
Packit 8480eb
	/* Don't update negative cache for included maps */ 
Packit 8480eb
	if (source && source->depth)
Packit 8480eb
		return;
Packit 8480eb
Packit 8480eb
	/* Don't update the wildcard */
Packit 8480eb
	if (strlen(name) == 1 && *name == '*')
Packit 8480eb
		return;
Packit 8480eb
Packit 8480eb
	/* Have we recorded the lookup fail for negative caching? */
Packit 8480eb
	me = lookup_source_mapent(ap, name, LKP_DISTINCT);
Packit 8480eb
	if (me)
Packit 8480eb
		/*
Packit 8480eb
		 *  Already exists in the cache, the mount fail updates
Packit 8480eb
		 *  will update negative timeout status.
Packit 8480eb
		 */
Packit 8480eb
		cache_unlock(me->mc);
Packit 8480eb
	else {
Packit 8480eb
		if (!defaults_disable_not_found_message()) {
Packit 8480eb
			/* This really should be a warning but the original
Packit 8480eb
			 * request for this needed it to be unconditional.
Packit 8480eb
			 * That produces, IMHO, unnecessary noise in the log
Packit 8480eb
			 * so a configuration option has been added to provide
Packit 8480eb
			 * the ability to turn it off.
Packit 8480eb
			 */
Packit 8480eb
			logmsg("key \"%s\" not found in map source(s).", name);
Packit 8480eb
		}
Packit 8480eb
Packit Bot 7679ed
		/* Doesn't exist in any source, just add it somewhere.
Packit Bot 7679ed
		 * Also take care to use the same map source used by
Packit Bot 7679ed
		 * map reads and key lookups for the update.
Packit Bot 7679ed
		 */
Packit 8480eb
		if (source)
Packit 8480eb
			map = source;
Packit 8480eb
		else
Packit Bot 7679ed
			map = lookup_get_map_source(entry);
Packit 8480eb
		if (map) {
Packit 8480eb
			time_t now = monotonic_time(NULL);
Packit 8480eb
			int rv = CHE_FAIL;
Packit 8480eb
Packit 8480eb
			cache_writelock(map->mc);
Packit 8480eb
			me = cache_lookup_distinct(map->mc, name);
Packit 8480eb
			if (me)
Packit 8480eb
				rv = cache_push_mapent(me, NULL);
Packit 8480eb
			else
Packit 8480eb
				rv = cache_update(map->mc, map, name, NULL, now);
Packit 8480eb
			if (rv != CHE_FAIL) {
Packit 8480eb
				me = cache_lookup_distinct(map->mc, name);
Packit 8480eb
				if (me)
Packit 8480eb
					me->status = now + ap->negative_timeout;
Packit 8480eb
			}
Packit 8480eb
			cache_unlock(map->mc);
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int lookup_nss_mount(struct autofs_point *ap, struct map_source *source, const char *name, int name_len)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry = ap->entry;
Packit 8480eb
	struct list_head nsslist;
Packit 8480eb
	struct list_head *head, *p;
Packit 8480eb
	struct nss_source *this;
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	enum nsswitch_status status;
Packit 8480eb
	int result = NSS_STATUS_UNKNOWN;
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * For each map source (ie. each entry for the mount
Packit 8480eb
	 * point in the master map) do the nss lookup to
Packit 8480eb
	 * locate the map and lookup the name.
Packit 8480eb
	 */
Packit 8480eb
	pthread_cleanup_push(master_source_lock_cleanup, entry);
Packit 8480eb
	master_source_readlock(entry);
Packit 8480eb
	if (source)
Packit 8480eb
		map = source;
Packit 8480eb
	else
Packit 8480eb
		map = entry->maps;
Packit 8480eb
	while (map) {
Packit 8480eb
		/*
Packit 8480eb
		 * Only consider map sources that have been read since 
Packit 8480eb
		 * the map entry was last updated.
Packit 8480eb
		 */
Packit 8480eb
		if (entry->age > map->age) {
Packit 8480eb
			status = NSS_STATUS_UNAVAIL;
Packit 8480eb
			map = map->next;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		sched_yield();
Packit 8480eb
Packit 8480eb
		if (map->type) {
Packit 8480eb
			result = do_name_lookup_mount(ap, map, name, name_len);
Packit 8480eb
			if (result == NSS_STATUS_SUCCESS)
Packit 8480eb
				break;
Packit 8480eb
Packit 8480eb
			map = map->next;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		/* If it starts with a '/' it has to be a file or LDAP map */
Packit 8480eb
		if (*map->argv[0] == '/') {
Packit 8480eb
			if (*(map->argv[0] + 1) == '/') {
Packit 8480eb
				char *tmp = strdup("ldap");
Packit 8480eb
				if (!tmp) {
Packit 8480eb
					map = map->next;
Packit 8480eb
					status = NSS_STATUS_TRYAGAIN;
Packit 8480eb
					continue;
Packit 8480eb
				}
Packit 8480eb
				map->type = tmp;
Packit 8480eb
				result = do_lookup_mount(ap, map, name, name_len);
Packit 8480eb
			} else
Packit 8480eb
				result = lookup_name_file_source_instance(ap, map, name, name_len);
Packit 8480eb
Packit 8480eb
			if (result == NSS_STATUS_SUCCESS)
Packit 8480eb
				break;
Packit 8480eb
Packit 8480eb
			map = map->next;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		INIT_LIST_HEAD(&nsslist);
Packit 8480eb
Packit 8480eb
		status = nsswitch_parse(&nsslist);
Packit 8480eb
		if (status) {
Packit 8480eb
			error(ap->logopt,
Packit 8480eb
			      "can't to read name service switch config.");
Packit 8480eb
			result = 1;
Packit 8480eb
			break;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		head = &nsslist;
Packit 8480eb
		list_for_each(p, head) {
Packit 8480eb
			this = list_entry(p, struct nss_source, list);
Packit 8480eb
Packit 8480eb
			if (map->flags & MAP_FLAG_FORMAT_AMD &&
Packit 8480eb
			    !strcmp(this->source, "sss")) {
Packit 8480eb
				warn(ap->logopt,
Packit 8480eb
				     "source sss is not available for amd maps.");
Packit 8480eb
				result = NSS_STATUS_UNAVAIL;
Packit 8480eb
				continue;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			result = lookup_map_name(this, ap, map, name, name_len);
Packit 8480eb
Packit 8480eb
			if (result == NSS_STATUS_UNKNOWN)
Packit 8480eb
				continue;
Packit 8480eb
Packit 8480eb
			status = check_nss_result(this, result);
Packit 8480eb
			if (status >= 0) {
Packit 8480eb
				map = NULL;
Packit 8480eb
				break;
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (!list_empty(&nsslist))
Packit 8480eb
			free_sources(&nsslist);
Packit 8480eb
Packit 8480eb
		if (!map)
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
	if (ap->state != ST_INIT)
Packit 8480eb
		send_map_update_request(ap);
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * The last source lookup will return NSS_STATUS_NOTFOUND if the
Packit 8480eb
	 * map exits and the key has not been found but the map may also
Packit 8480eb
	 * not exist in which case the key is also not found.
Packit 8480eb
	 */
Packit 8480eb
	if (result == NSS_STATUS_NOTFOUND || result == NSS_STATUS_UNAVAIL)
Packit 8480eb
		update_negative_cache(ap, source, name);
Packit 8480eb
	pthread_cleanup_pop(1);
Packit 8480eb
Packit 8480eb
	return !result;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void lookup_close_lookup_instances(struct map_source *map)
Packit 8480eb
{
Packit 8480eb
	struct map_source *instance;
Packit 8480eb
Packit 8480eb
	instance = map->instance;
Packit 8480eb
	while (instance) {
Packit 8480eb
		lookup_close_lookup_instances(instance);
Packit 8480eb
		instance = instance->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (map->lookup) {
Packit 8480eb
		close_lookup(map->lookup);
Packit 8480eb
		map->lookup = NULL;
Packit 8480eb
	}
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void lookup_close_lookup(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	struct map_source *map;
Packit 8480eb
Packit 8480eb
	map = ap->entry->maps;
Packit 8480eb
	if (!map)
Packit 8480eb
		return;
Packit 8480eb
Packit 8480eb
	while (map) {
Packit 8480eb
		lookup_close_lookup_instances(map);
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static char *make_fullpath(struct autofs_point *ap, const char *key)
Packit 8480eb
{
Packit 8480eb
	char *path = NULL;
Packit 8480eb
	int l;
Packit 8480eb
Packit 8480eb
	if (*key != '/')
Packit 8480eb
		path = make_browse_path(ap->logopt, ap->path, key, ap->pref);
Packit 8480eb
	else {
Packit 8480eb
		l = strlen(key) + 1;
Packit 8480eb
		if (l > KEY_MAX_LEN)
Packit 8480eb
			goto out;
Packit 8480eb
		path = malloc(l);
Packit 8480eb
		if (!path)
Packit 8480eb
			goto out;
Packit 8480eb
		strcpy(path, key);
Packit 8480eb
	}
Packit 8480eb
out:
Packit 8480eb
	return path;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, time_t age)
Packit 8480eb
{
Packit 8480eb
	struct mapent *me, *this;
Packit 8480eb
	char *path;
Packit 8480eb
	int status = CHE_FAIL;
Packit 8480eb
Packit 8480eb
	me = cache_enumerate(mc, NULL);
Packit 8480eb
	while (me) {
Packit 8480eb
		struct mapent *valid;
Packit 8480eb
		char *key = NULL, *next_key = NULL;
Packit 8480eb
Packit 8480eb
		if (me->age >= age) {
Packit 8480eb
			/*
Packit 8480eb
			 * Reset time of last fail for valid map entries to
Packit 8480eb
			 * force entry update and subsequent mount retry.
Packit 8480eb
			 * A map entry that's still invalid after a read
Packit 8480eb
			 * may have been created by a failed wildcard lookup
Packit 8480eb
			 * so reset the status on those too.
Packit 8480eb
			 */
Packit 8480eb
			if (me->mapent || cache_lookup(mc, "*"))
Packit 8480eb
				me->status = 0;
Packit 8480eb
			me = cache_enumerate(mc, me);
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit Bot ed9139
		if (ap->type == LKP_INDIRECT) {
Packit Bot 36a717
			/* Don't prune offset map entries since they are
Packit Bot 36a717
			 * created on demand and managed by expire and don't
Packit Bot 36a717
			 * prune the multi-map owner map entry.
Packit Bot 36a717
			 */
Packit Bot 7bc25c
			if (*me->key == '/' || IS_MM_ROOT(me)) {
Packit Bot 36a717
				me = cache_enumerate(mc, me);
Packit Bot 36a717
				continue;
Packit Bot 36a717
			}
Packit Bot 36a717
Packit Bot ed9139
			/* If the map hasn't been read (nobrowse
Packit Bot ed9139
			 * indirect mounts) then keep cached entries
Packit Bot ed9139
			 * for POSITIVE_TIMEOUT.
Packit Bot ed9139
			 */
Packit Bot ed9139
			if (!(ap->flags & (MOUNT_FLAG_GHOST |
Packit Bot ed9139
					   MOUNT_FLAG_AMD_CACHE_ALL))) {
Packit Bot ed9139
				time_t until = me->age + POSITIVE_TIMEOUT;
Packit Bot ed9139
				if ((long) age - (long) until < 0) {
Packit Bot ed9139
					me = cache_enumerate(mc, me);
Packit Bot ed9139
					continue;
Packit Bot ed9139
				}
Packit Bot ed9139
			}
Packit Bot ed9139
		}
Packit Bot ed9139
Packit 8480eb
		key = strdup(me->key);
Packit 8480eb
		/* Don't consider any entries with a wildcard */
Packit 8480eb
		if (!key || strchr(key, '*')) {
Packit 8480eb
			if (key)
Packit 8480eb
				free(key);
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		path = make_fullpath(ap, key);
Packit 8480eb
		if (!path) {
Packit 8480eb
			warn(ap->logopt, "can't malloc storage for path");
Packit 8480eb
			free(key);
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		/*
Packit 8480eb
		 * If this key has another valid entry we want to prune it,
Packit 8480eb
		 * even if it's a mount, as the valid entry will take the
Packit 8480eb
		 * mount if it is a direct mount or it's just a stale indirect
Packit 8480eb
		 * cache entry.
Packit 8480eb
		 */
Packit 8480eb
		valid = lookup_source_valid_mapent(ap, key, LKP_DISTINCT);
Packit 8480eb
		if (valid && valid->mc == mc) {
Packit 8480eb
			 /*
Packit 8480eb
			  * We've found a map entry that has been removed from
Packit Bot e11954
			  * the current cache so it isn't really valid. Set the
Packit Bot e11954
			  * mapent negative to prevent further mount requests
Packit Bot e11954
			  * using the cache entry.
Packit 8480eb
			  */
Packit Bot e11954
			debug(ap->logopt, "removed map entry detected, mark negative");
Packit Bot e11954
			if (valid->mapent) {
Packit Bot e11954
				free(valid->mapent);
Packit Bot e11954
				valid->mapent = NULL;
Packit Bot e11954
			}
Packit 8480eb
			cache_unlock(valid->mc);
Packit 8480eb
			valid = NULL;
Packit 8480eb
		}
Packit 8480eb
		if (!valid &&
Packit Bot 28887b
		    is_mounted(path, MNTS_REAL)) {
Packit Bot e11954
			debug(ap->logopt, "prune posponed, %s mounted", path);
Packit 8480eb
			free(key);
Packit 8480eb
			free(path);
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
		if (valid)
Packit 8480eb
			cache_unlock(valid->mc);
Packit 8480eb
Packit Bot 350828
		me = cache_enumerate(mc, me);
Packit 8480eb
		if (me)
Packit 8480eb
			next_key = strdup(me->key);
Packit 8480eb
Packit 8480eb
		cache_unlock(mc);
Packit 8480eb
Packit 8480eb
		cache_writelock(mc);
Packit 8480eb
		this = cache_lookup_distinct(mc, key);
Packit 8480eb
		if (!this) {
Packit 8480eb
			cache_unlock(mc);
Packit 8480eb
			goto next;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (valid)
Packit 8480eb
			cache_delete(mc, key);
Packit Bot 28887b
		else if (!is_mounted(path, MNTS_AUTOFS)) {
Packit 8480eb
			dev_t devid = ap->dev;
Packit 8480eb
			status = CHE_FAIL;
Packit 8480eb
			if (ap->type == LKP_DIRECT)
Packit 8480eb
				devid = this->dev;
Packit 8480eb
			if (this->ioctlfd == -1)
Packit 8480eb
				status = cache_delete(mc, key);
Packit 8480eb
			if (status != CHE_FAIL) {
Packit 8480eb
				if (ap->type == LKP_INDIRECT) {
Packit 8480eb
					if (ap->flags & MOUNT_FLAG_GHOST)
Packit 8480eb
						rmdir_path(ap, path, devid);
Packit 8480eb
				} else
Packit 8480eb
					rmdir_path(ap, path, devid);
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
		cache_unlock(mc);
Packit 8480eb
Packit 8480eb
next:
Packit 8480eb
		cache_readlock(mc);
Packit 8480eb
		if (next_key) {
Packit Bot 350828
			/* The lock release and reaquire above can mean
Packit Bot 350828
			 * a number of things could happen.
Packit Bot 350828
			 *
Packit Bot 350828
			 * First, mapents could be added between the
Packit Bot 350828
			 * current mapent and the mapent of next_key.
Packit Bot 350828
			 * Don't care about that because there's no
Packit Bot 350828
			 * need to prune newly added entries.
Packit Bot 350828
			 *
Packit Bot 350828
			 * Second, the next mapent data could have
Packit Bot 350828
			 * changed. Don't care about that either since
Packit Bot 350828
			 * we are looking to prune stale map entries
Packit Bot 350828
			 * and don't care when they become stale.
Packit Bot 350828
			 *
Packit Bot 350828
			 * Finally, the mapent of next_key could have
Packit Bot 350828
			 * gone away. Again don't care about this either,
Packit Bot 350828
			 * the loop will exit prematurely so just wait
Packit Bot 350828
			 * until the next prune and try again.
Packit Bot 350828
			 */
Packit 8480eb
			me = cache_lookup_distinct(mc, next_key);
Packit 8480eb
			free(next_key);
Packit 8480eb
		}
Packit 8480eb
		free(key);
Packit 8480eb
		free(path);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int lookup_prune_cache(struct autofs_point *ap, time_t age)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry = ap->entry;
Packit 8480eb
	struct map_source *map;
Packit 8480eb
Packit 8480eb
	pthread_cleanup_push(master_source_lock_cleanup, entry);
Packit 8480eb
	master_source_readlock(entry);
Packit 8480eb
Packit 8480eb
	map = entry->maps;
Packit 8480eb
	while (map) {
Packit 8480eb
		/* Is the map stale */
Packit 8480eb
		if (!map->stale && !check_stale_instances(map)) {
Packit 8480eb
			map = map->next;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
		pthread_cleanup_push(cache_lock_cleanup, map->mc);
Packit 8480eb
		cache_readlock(map->mc);
Packit 8480eb
		lookup_prune_one_cache(ap, map->mc, age);
Packit 8480eb
		pthread_cleanup_pop(1);
Packit 8480eb
		clear_stale_instances(map);
Packit 8480eb
		map->stale = 0;
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	pthread_cleanup_pop(1);
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* Return with cache readlock held */
Packit 8480eb
struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *key, unsigned int type)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry = ap->entry;
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	struct mapent_cache *mc;
Packit 8480eb
	struct mapent *me = NULL;
Packit 8480eb
Packit 8480eb
	map = entry->maps;
Packit 8480eb
	while (map) {
Packit 8480eb
		/*
Packit 8480eb
		 * Only consider map sources that have been read since
Packit 8480eb
		 * the map entry was last updated.
Packit 8480eb
		 */
Packit 8480eb
		if (ap->entry->age > map->age) {
Packit 8480eb
			map = map->next;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		mc = map->mc;
Packit 8480eb
		cache_readlock(mc);
Packit 8480eb
		if (type == LKP_DISTINCT)
Packit 8480eb
			me = cache_lookup_distinct(mc, key);
Packit 8480eb
		else
Packit 8480eb
			me = cache_lookup(mc, key);
Packit 8480eb
		if (me)
Packit 8480eb
			break;
Packit 8480eb
		cache_unlock(mc);
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return me;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* Return with cache readlock held */
Packit 8480eb
struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key, unsigned int type)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry = ap->entry;
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	struct mapent_cache *mc;
Packit 8480eb
	struct mapent *me = NULL;
Packit 8480eb
Packit 8480eb
	map = entry->maps;
Packit 8480eb
	while (map) {
Packit 8480eb
		mc = map->mc;
Packit 8480eb
		cache_readlock(mc);
Packit 8480eb
		if (type == LKP_DISTINCT)
Packit 8480eb
			me = cache_lookup_distinct(mc, key);
Packit 8480eb
		else
Packit 8480eb
			me = cache_lookup(mc, key);
Packit 8480eb
		if (me)
Packit 8480eb
			break;
Packit 8480eb
		cache_unlock(mc);
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (me && me->mc != mc)
Packit 8480eb
		error(LOGOPT_ANY, "mismatching mc in cache", me->key);
Packit 8480eb
Packit 8480eb
	return me;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int lookup_source_close_ioctlfd(struct autofs_point *ap, const char *key)
Packit 8480eb
{
Packit 8480eb
	struct master_mapent *entry = ap->entry;
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	struct mapent_cache *mc;
Packit 8480eb
	struct mapent *me;
Packit 8480eb
	int ret = 0;
Packit 8480eb
Packit 8480eb
	map = entry->maps;
Packit 8480eb
	while (map) {
Packit 8480eb
		mc = map->mc;
Packit 8480eb
		cache_readlock(mc);
Packit 8480eb
		me = cache_lookup_distinct(mc, key);
Packit 8480eb
		if (me) {
Packit 8480eb
			if (me->ioctlfd != -1) {
Packit 8480eb
				struct ioctl_ops *ops = get_ioctl_ops();
Packit 8480eb
				ops->close(ap->logopt, me->ioctlfd);
Packit 8480eb
				me->ioctlfd = -1;
Packit 8480eb
			}
Packit 8480eb
			cache_unlock(mc);
Packit 8480eb
			ret = 1;
Packit 8480eb
			break;
Packit 8480eb
		}
Packit 8480eb
		cache_unlock(mc);
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb