From 6bbd1101e27f556ca1c39cbb4714b78edd47bc3e Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Mar 05 2015 13:28:24 +0000 Subject: import autofs-5.0.7-48.el7 --- diff --git a/SOURCES/autofs-5.0.7-add-short-host-name-standard-marco-variable.patch b/SOURCES/autofs-5.0.7-add-short-host-name-standard-marco-variable.patch new file mode 100644 index 0000000..5d0a7e5 --- /dev/null +++ b/SOURCES/autofs-5.0.7-add-short-host-name-standard-marco-variable.patch @@ -0,0 +1,70 @@ +autofs-5.0.7 - add short host name standard marco variable + +From: Ian Kent + +Sometimes the short hostname (without the domain part) could be useful. +Add this to the standard additional macro variables, in particular, to +compliment the ${HOST} macro. +--- + CHANGELOG | 1 + + man/autofs.5 | 2 +- + modules/parse_sun.c | 13 +++++++++++++ + 3 files changed, 15 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -77,6 +77,7 @@ + - fix fix options compare. + - fix max() declaration. + - setup program map env from macro table. ++- add short host name standard marco variable. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/man/autofs.5 ++++ autofs-5.0.7/man/autofs.5 +@@ -170,7 +170,7 @@ UID The user login ID + GROUP The user group name + GID The user group ID + HOME The user home directory +-HOST Hostname (uname -n) ++SHOST Short hostname (domain part removed if present) + .fi + .RE + .sp +--- autofs-5.0.7.orig/modules/parse_sun.c ++++ autofs-5.0.7/modules/parse_sun.c +@@ -107,6 +107,7 @@ static struct substvar *addstdenv(struct + + tsv = pthread_getspecific(key_thread_stdenv_vars); + if (tsv) { ++ struct substvar *mv; + int ret; + long num; + +@@ -121,6 +122,17 @@ static struct substvar *addstdenv(struct + list = macro_addvar(list, "USER", 4, tsv->user); + list = macro_addvar(list, "GROUP", 5, tsv->group); + list = macro_addvar(list, "HOME", 4, tsv->home); ++ mv = macro_findvar(list, "HOST", 4); ++ if (mv) { ++ char *shost = strdup(mv->val); ++ if (shost) { ++ char *dot = strchr(shost, '.'); ++ if (dot) ++ *dot = '\0'; ++ list = macro_addvar(list, "SHOST", 5, shost); ++ free(shost); ++ } ++ } + } + return list; + } +@@ -134,6 +146,7 @@ static struct substvar *removestdenv(str + list = macro_removevar(list, "HOME", 4); + list = macro_removevar(list, "GID", 3); + list = macro_removevar(list, "GROUP", 5); ++ list = macro_removevar(list, "SHOST", 5); + return list; + } + diff --git a/SOURCES/autofs-5.0.7-add-std-vars-to-program-map-invocation.patch b/SOURCES/autofs-5.0.7-add-std-vars-to-program-map-invocation.patch new file mode 100644 index 0000000..eb61bd0 --- /dev/null +++ b/SOURCES/autofs-5.0.7-add-std-vars-to-program-map-invocation.patch @@ -0,0 +1,171 @@ +autofs-5.0.7 - add std vars to program map invocation + +From: Ian Kent + +Program maps currently don't have the standard macro variables set +in the environemt when they run. + +Also, program maps aren't necessarily executed within a shell so +setting the standard variables in the environment needs to be done +the same way it's done by the Sun map parser. +--- + CHANGELOG | 1 + include/mounts.h | 3 ++ + lib/mounts.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ + modules/lookup_program.c | 2 + + modules/parse_sun.c | 51 ----------------------------------------------- + 5 files changed, 57 insertions(+), 51 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -79,6 +79,7 @@ + - setup program map env from macro table. + - add short host name standard marco variable. + - fix symlink fail message in mount_bind.c. ++- add std vars to program map invocation. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/include/mounts.h ++++ autofs-5.0.7/include/mounts.h +@@ -85,6 +85,9 @@ unsigned int linux_version_code(void); + int check_nfs_mount_version(struct nfs_mount_vers *, struct nfs_mount_vers *); + extern unsigned int nfs_mount_uses_string_options; + ++struct substvar *addstdenv(struct substvar *sv); ++struct substvar *removestdenv(struct substvar *sv); ++ + unsigned int query_kproto_ver(void); + unsigned int get_kver_major(void); + unsigned int get_kver_minor(void); +--- autofs-5.0.7.orig/lib/mounts.c ++++ autofs-5.0.7/lib/mounts.c +@@ -303,6 +303,57 @@ int check_nfs_mount_version(struct nfs_m + } + #endif + ++struct substvar *addstdenv(struct substvar *sv) ++{ ++ struct substvar *list = sv; ++ struct thread_stdenv_vars *tsv; ++ char numbuf[16]; ++ ++ tsv = pthread_getspecific(key_thread_stdenv_vars); ++ if (tsv) { ++ const struct substvar *mv; ++ int ret; ++ long num; ++ ++ num = (long) tsv->uid; ++ ret = sprintf(numbuf, "%ld", num); ++ if (ret > 0) ++ list = macro_addvar(list, "UID", 3, numbuf); ++ num = (long) tsv->gid; ++ ret = sprintf(numbuf, "%ld", num); ++ if (ret > 0) ++ list = macro_addvar(list, "GID", 3, numbuf); ++ list = macro_addvar(list, "USER", 4, tsv->user); ++ list = macro_addvar(list, "GROUP", 5, tsv->group); ++ list = macro_addvar(list, "HOME", 4, tsv->home); ++ mv = macro_findvar(list, "HOST", 4); ++ if (mv) { ++ char *shost = strdup(mv->val); ++ if (shost) { ++ char *dot = strchr(shost, '.'); ++ if (dot) ++ *dot = '\0'; ++ list = macro_addvar(list, "SHOST", 5, shost); ++ free(shost); ++ } ++ } ++ } ++ return list; ++} ++ ++struct substvar *removestdenv(struct substvar *sv) ++{ ++ struct substvar *list = sv; ++ ++ list = macro_removevar(list, "UID", 3); ++ list = macro_removevar(list, "USER", 4); ++ list = macro_removevar(list, "HOME", 4); ++ list = macro_removevar(list, "GID", 3); ++ list = macro_removevar(list, "GROUP", 5); ++ list = macro_removevar(list, "SHOST", 5); ++ return list; ++} ++ + /* + * Make common autofs mount options string + */ +--- autofs-5.0.7.orig/modules/lookup_program.c ++++ autofs-5.0.7/modules/lookup_program.c +@@ -271,6 +271,8 @@ int lookup_mount(struct autofs_point *ap + */ + if (ctxt->mapfmt && strcmp(ctxt->mapfmt, "MAPFMT_DEFAULT")) { + struct parse_context *pctxt = (struct parse_context *) ctxt->parse->context; ++ /* Add standard environment as seen by sun map parser */ ++ pctxt->subst = addstdenv(pctxt->subst); + macro_setenv(pctxt->subst); + } + execl(ctxt->mapname, ctxt->mapname, name, NULL); +--- autofs-5.0.7.orig/modules/parse_sun.c ++++ autofs-5.0.7/modules/parse_sun.c +@@ -99,57 +99,6 @@ static void kill_context(struct parse_co + free(ctxt); + } + +-static struct substvar *addstdenv(struct substvar *sv) +-{ +- struct substvar *list = sv; +- struct thread_stdenv_vars *tsv; +- char numbuf[16]; +- +- tsv = pthread_getspecific(key_thread_stdenv_vars); +- if (tsv) { +- struct substvar *mv; +- int ret; +- long num; +- +- num = (long) tsv->uid; +- ret = sprintf(numbuf, "%ld", num); +- if (ret > 0) +- list = macro_addvar(list, "UID", 3, numbuf); +- num = (long) tsv->gid; +- ret = sprintf(numbuf, "%ld", num); +- if (ret > 0) +- list = macro_addvar(list, "GID", 3, numbuf); +- list = macro_addvar(list, "USER", 4, tsv->user); +- list = macro_addvar(list, "GROUP", 5, tsv->group); +- list = macro_addvar(list, "HOME", 4, tsv->home); +- mv = macro_findvar(list, "HOST", 4); +- if (mv) { +- char *shost = strdup(mv->val); +- if (shost) { +- char *dot = strchr(shost, '.'); +- if (dot) +- *dot = '\0'; +- list = macro_addvar(list, "SHOST", 5, shost); +- free(shost); +- } +- } +- } +- return list; +-} +- +-static struct substvar *removestdenv(struct substvar *sv) +-{ +- struct substvar *list = sv; +- +- list = macro_removevar(list, "UID", 3); +- list = macro_removevar(list, "USER", 4); +- list = macro_removevar(list, "HOME", 4); +- list = macro_removevar(list, "GID", 3); +- list = macro_removevar(list, "GROUP", 5); +- list = macro_removevar(list, "SHOST", 5); +- return list; +-} +- + /* + * $- and &-expand a Sun-style map entry and return the length of the entry. + * If "dst" is NULL, just count the length. diff --git a/SOURCES/autofs-5.0.7-allow-use-of-hosts-map-in-maps.patch b/SOURCES/autofs-5.0.7-allow-use-of-hosts-map-in-maps.patch new file mode 100644 index 0000000..6a18673 --- /dev/null +++ b/SOURCES/autofs-5.0.7-allow-use-of-hosts-map-in-maps.patch @@ -0,0 +1,231 @@ +autofs-5.0.7 - allow use of hosts map in maps + +From: Ian Kent + +At the moment the internal hosts map can only be use as an entry in the +master map but there's no reason (I can think of so far) that it shouldn't +be possible to use it in map entries. +--- + lib/parse_subs.c | 17 ++++++----- + modules/mount_autofs.c | 29 ++++++++++++++++---- + modules/parse_sun.c | 71 +++++++++++++++++++++++++++++++------------------ + 3 files changed, 80 insertions(+), 37 deletions(-) + +--- autofs-5.0.7.orig/lib/parse_subs.c ++++ autofs-5.0.7/lib/parse_subs.c +@@ -35,6 +35,7 @@ static struct types map_type[] = { + { "ldaps", 5 }, + { "hesiod", 6 }, + { "userdir", 7 }, ++ { "hosts", 5 }, + }; + static unsigned int map_type_count = sizeof(map_type)/sizeof(struct types); + +@@ -384,7 +385,7 @@ struct map_type_info *parse_map_type_inf + return NULL; + } else { + *pos++ = '\0'; +- while (*pos == ' ') ++ while (*pos && *pos == ' ') + *pos++ = '\0'; + map = pos; + break; +@@ -412,7 +413,7 @@ struct map_type_info *parse_map_type_inf + return NULL; + } else { + *pos++ = '\0'; +- while (*pos == ' ') ++ while (*pos && *pos == ' ') + *pos++ = '\0'; + map = pos; + break; +@@ -458,11 +459,13 @@ struct map_type_info *parse_map_type_inf + } + } + +- info->map = strdup(map); +- if (!info->map) { +- free(buf); +- free_map_type_info(info); +- return NULL; ++ if (map) { ++ info->map = strdup(map); ++ if (!info->map) { ++ free(buf); ++ free_map_type_info(info); ++ return NULL; ++ } + } + + free(buf); +--- autofs-5.0.7.orig/modules/mount_autofs.c ++++ autofs-5.0.7/modules/mount_autofs.c +@@ -62,6 +62,7 @@ int mount_mount(struct autofs_point *ap, + char buf[MAX_ERR_BUF]; + char *options, *p; + int len, ret; ++ int hosts = 0; + + /* Root offset of multi-mount */ + len = strlen(root); +@@ -123,6 +124,8 @@ int mount_mount(struct autofs_point *ap, + ghost = 1; + else if (strncmp(cp, "symlink", 7) == 0) + symlnk = 1; ++ else if (strncmp(cp, "hosts", 5) == 0) ++ hosts = 1; + else if (strncmp(cp, "timeout=", 8) == 0) { + char *val = strchr(cp, '='); + unsigned tout; +@@ -164,7 +167,10 @@ int mount_mount(struct autofs_point *ap, + if (symlnk) + nap->flags |= MOUNT_FLAG_SYMLINK; + +- argc = 1; ++ if (hosts) ++ argc = 0; ++ else ++ argc = 1; + + if (options) { + char *t = options; +@@ -176,14 +182,27 @@ int mount_mount(struct autofs_point *ap, + } + argv = (const char **) alloca((argc + 1) * sizeof(char *)); + +- argc = 1; +- +- if (!(info = parse_map_type_info(what))) { ++ if (hosts) ++ argc = 0; ++ else ++ argc = 1; ++ ++ /* ++ * If a mount of a hosts map is being requested it will come ++ * ro us via the options. Catch that below when processing the ++ * option and create type info struct then. ++ */ ++ if (hosts) ++ info = parse_map_type_info("hosts:"); ++ else ++ info = parse_map_type_info(what); ++ if (!info) { + error(ap->logopt, MODPREFIX "failed to parse map info"); + master_free_mapent(entry); + return 1; + } +- argv[0] = info->map; ++ if (info->map) ++ argv[0] = info->map; + + if (options) { + p = options; +--- autofs-5.0.7.orig/modules/parse_sun.c ++++ autofs-5.0.7/modules/parse_sun.c +@@ -695,14 +695,18 @@ static int sun_mount(struct autofs_point + rv = mount_nfs->mount_mount(ap, root, mountpoint, strlen(mountpoint), + what, fstype, options, mount_nfs->context); + } else { +- what = alloca(loclen + 1); +- if (*loc == ':') { +- loclen--; +- memcpy(what, loc + 1, loclen); +- what[loclen] = '\0'; +- } else { +- memcpy(what, loc, loclen); +- what[loclen] = '\0'; ++ if (!loclen) ++ what = NULL; ++ else { ++ what = alloca(loclen + 1); ++ if (*loc == ':') { ++ loclen--; ++ memcpy(what, loc + 1, loclen); ++ what[loclen] = '\0'; ++ } else { ++ memcpy(what, loc, loclen); ++ what[loclen] = '\0'; ++ } + } + + debug(ap->logopt, MODPREFIX +@@ -799,7 +803,8 @@ update_offset_entry(struct autofs_point + + mc = source->mc; + +- if (!*path || !*loc) { ++ /* Internal hosts map may have loc == NULL */ ++ if (!*path) { + error(ap->logopt, + MODPREFIX "syntax error in offset %s -> %s", path, loc); + return CHE_FAIL; +@@ -833,8 +838,10 @@ update_offset_entry(struct autofs_point + if (*myoptions) { + strcpy(m_mapent, "-"); + strcat(m_mapent, myoptions); +- strcat(m_mapent, " "); +- strcat(m_mapent, loc); ++ if (loc) { ++ strcat(m_mapent, " "); ++ strcat(m_mapent, loc); ++ } + } else + strcpy(m_mapent, loc); + +@@ -1435,13 +1442,17 @@ int parse_mount(struct autofs_point *ap, + + l = parse_mapent(p, options, &myoptions, &loc, ap->logopt); + if (!l) { +- cache_delete_offset_list(mc, name); +- cache_multi_unlock(me); +- cache_unlock(mc); +- free(path); +- free(options); +- pthread_setcancelstate(cur_state, NULL); +- return 1; ++ if (!(strstr(myoptions, "fstype=autofs") && ++ strstr(myoptions, "hosts"))) { ++ error(LOGOPT_ANY, "I think I'm a hosts map? l %d", l); ++ cache_delete_offset_list(mc, name); ++ cache_multi_unlock(me); ++ cache_unlock(mc); ++ free(path); ++ free(options); ++ pthread_setcancelstate(cur_state, NULL); ++ return 1; ++ } + } + + p += l; +@@ -1592,13 +1603,23 @@ int parse_mount(struct autofs_point *ap, + p = skipspace(p); + } + +- loclen = strlen(loc); +- if (loclen == 0) { +- free(loc); +- free(options); +- error(ap->logopt, +- MODPREFIX "entry %s is empty!", name); +- return 1; ++ /* ++ * If options are asking for a hosts map loc should be ++ * NULL but we see it can contain junk, so .... ++ */ ++ if ((strstr(options, "fstype=autofs") && ++ strstr(options, "hosts"))) { ++ loc = NULL; ++ loclen = 0; ++ } else { ++ loclen = strlen(loc); ++ if (loclen == 0) { ++ free(loc); ++ free(options); ++ error(ap->logopt, ++ MODPREFIX "entry %s is empty!", name); ++ return 1; ++ } + } + + debug(ap->logopt, diff --git a/SOURCES/autofs-5.0.7-fix-bad-mkdir-permission-on-create.patch b/SOURCES/autofs-5.0.7-fix-bad-mkdir-permission-on-create.patch new file mode 100644 index 0000000..2152c8a --- /dev/null +++ b/SOURCES/autofs-5.0.7-fix-bad-mkdir-permission-on-create.patch @@ -0,0 +1,38 @@ +autofs-5.0.7 - fix bad mkdir permission on create + +From: Ian Kent + +Reported by Gordon Lack (gordon[dot]m[dot]lack[at]gsk[dot]com). + +If the automount daemon needs to create a directory (hierarchy) for an +automount and it is started up with a umask of 027 (or similar) then it +creates unusable directories (permission == 550). +--- + CHANGELOG | 1 + + daemon/automount.c | 5 ++++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -88,6 +88,7 @@ + - check for bind onto self in mount_bind.c. + - fix symlink expire. + - fix master map type check. ++- fix bad mkdir permission on create. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/automount.c ++++ autofs-5.0.7/daemon/automount.c +@@ -122,7 +122,10 @@ static int do_mkdir(const char *parent, + status = statfs(parent, &fs); + if ((status != -1 && fs.f_type == (__SWORD_TYPE) AUTOFS_SUPER_MAGIC) || + contained_in_local_fs(path)) { +- if (mkdir(path, mode) == -1) { ++ mode_t mask = umask(0022); ++ int ret = mkdir(path, mode); ++ (void) umask(mask); ++ if (ret == -1) { + errno = EACCES; + return 0; + } diff --git a/SOURCES/autofs-5.0.7-fix-compilation-of-lookup_ldap_c-without-sasl.patch b/SOURCES/autofs-5.0.7-fix-compilation-of-lookup_ldap_c-without-sasl.patch new file mode 100644 index 0000000..1e0350a --- /dev/null +++ b/SOURCES/autofs-5.0.7-fix-compilation-of-lookup_ldap_c-without-sasl.patch @@ -0,0 +1,216 @@ +autofs-5.0.7 - fix compilation of lookup_ldap.c without sasl + +From: Dustin Polke + +See https://bugs.gentoo.org/show_bug.cgi?id=361899 for more info. + +Edited by: Ian Kent +- fix parse_ldap_config() is needed by ldap but previously excluded. +- exclude other references to ctxt->extern_cert and ctxt->extern_key. +- prevent memory leak if present in config but not used. +- remove now unused set_env(). +--- + CHANGELOG | 1 + + include/lookup_ldap.h | 4 ++-- + lib/Makefile | 4 ++++ + modules/Makefile | 6 ++++-- + modules/lookup_ldap.c | 18 +++++++++++++----- + 5 files changed, 24 insertions(+), 9 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -82,6 +82,7 @@ + - add std vars to program map invocation. + - check for existing offset mount before mounting. + - fix cache readlock not taken on lookup. ++- fix compilation of lookup_ldap.c without sasl. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/include/lookup_ldap.h ++++ autofs-5.0.7/include/lookup_ldap.h +@@ -11,6 +11,8 @@ + #include + #endif + ++#include ++ + #include "list.h" + #include "dclist.h" + +@@ -92,7 +94,6 @@ struct lookup_context { + }; + + +-#ifdef WITH_SASL + #define LDAP_AUTH_CONF_FILE "test" + + #define LDAP_TLS_DONT_USE 0 +@@ -104,7 +105,6 @@ struct lookup_context { + #define LDAP_AUTH_REQUIRED 0x0002 + #define LDAP_AUTH_AUTODETECT 0x0004 + #define LDAP_NEED_AUTH (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT) +-#endif + + #define LDAP_AUTH_USESIMPLE 0x0008 + +--- autofs-5.0.7.orig/lib/Makefile ++++ autofs-5.0.7/lib/Makefile +@@ -24,6 +24,10 @@ CFLAGS += -I../include -fPIC -D_GNU_SOUR + CFLAGS += -DAUTOFS_MAP_DIR=\"$(autofsmapdir)\" + CFLAGS += -DAUTOFS_CONF_DIR=\"$(autofsconfdir)\" + ++ifeq ($(LDAP), 1) ++ CFLAGS += $(XML_FLAGS) $(XML_LIBS) ++endif ++ + .PHONY: all install clean + + all: autofs.a +--- autofs-5.0.7.orig/modules/Makefile ++++ autofs-5.0.7/modules/Makefile +@@ -45,10 +45,12 @@ endif + ifeq ($(LDAP), 1) + SRCS += lookup_ldap.c + MODS += lookup_ldap.so ++ LDAP_FLAGS += $(XML_FLAGS) -DLDAP_THREAD_SAFE ++ LIBLDAP += $(XML_LIBS) + ifeq ($(SASL), 1) + SASL_OBJ = cyrus-sasl.o cyrus-sasl-extern.o +- LDAP_FLAGS += $(SASL_FLAGS) $(XML_FLAGS) $(KRB5_FLAGS) -DLDAP_THREAD_SAFE +- LIBLDAP += $(LIBSASL) $(XML_LIBS) $(KRB5_LIBS) ++ LDAP_FLAGS += $(SASL_FLAGS) $(KRB5_FLAGS) ++ LIBLDAP += $(LIBSASL) $(KRB5_LIBS) + endif + endif + +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -66,6 +66,7 @@ struct ldap_search_params { + + static int decode_percent_hack(const char *, char **); + ++#ifdef WITH_SASL + static int set_env(unsigned logopt, const char *name, const char *val) + { + int ret = setenv(name, val, 1); +@@ -75,6 +76,7 @@ static int set_env(unsigned logopt, cons + } + return 1; + } ++#endif + + #ifndef HAVE_LDAP_CREATE_PAGE_CONTROL + int ldap_create_page_control(LDAP *ldap, ber_int_t pagesize, +@@ -183,9 +185,9 @@ int unbind_ldap_connection(unsigned logo + { + int rv; + +-#ifdef WITH_SASL + if (ctxt->use_tls == LDAP_TLS_RELEASE) + ctxt->use_tls = LDAP_TLS_INIT; ++#ifdef WITH_SASL + autofs_sasl_unbind(ctxt); + #endif + +@@ -243,7 +245,6 @@ LDAP *init_ldap_connection(unsigned logo + info(logopt, MODPREFIX "failed to set connection timeout to %d", + net_timeout.tv_sec); + +-#ifdef WITH_SASL + if (ctxt->use_tls) { + if (ctxt->version == 2) { + if (ctxt->tls_required) { +@@ -272,7 +273,6 @@ LDAP *init_ldap_connection(unsigned logo + } + ctxt->use_tls = LDAP_TLS_RELEASE; + } +-#endif + + return ldap; + } +@@ -585,10 +585,12 @@ static LDAP *do_connect(unsigned logopt, + { + LDAP *ldap; + ++#ifdef WITH_SASL + if (ctxt->extern_cert && ctxt->extern_key) { + set_env(logopt, ENV_LDAPTLS_CERT, ctxt->extern_cert); + set_env(logopt, ENV_LDAPTLS_KEY, ctxt->extern_key); + } ++#endif + + ldap = init_ldap_connection(logopt, uri, ctxt); + if (ldap) { +@@ -791,7 +793,6 @@ find_server: + return ldap; + } + +-#ifdef WITH_SASL + int get_property(unsigned logopt, xmlNodePtr node, const char *prop, char **value) + { + xmlChar *ret; +@@ -812,6 +813,7 @@ int get_property(unsigned logopt, xmlNod + return 0; + } + ++#ifdef WITH_SASL + /* + * For plain text, login and digest-md5 authentication types, we need + * user and password credentials. +@@ -824,6 +826,7 @@ int authtype_requires_creds(const char * + return 1; + return 0; + } ++#endif + + /* + * Returns: +@@ -1056,6 +1059,7 @@ auth_fail: + } + } else if (auth_required == LDAP_AUTH_REQUIRED && + (authtype && !strncmp(authtype, "EXTERNAL", 8))) { ++#ifdef WITH_SASL + ret = get_property(logopt, root, "external_cert", &extern_cert); + ret |= get_property(logopt, root, "external_key", &extern_key); + /* +@@ -1074,6 +1078,7 @@ auth_fail: + if (extern_key) + free(extern_key); + } ++#endif + } + + /* +@@ -1094,8 +1099,10 @@ auth_fail: + ctxt->secret = secret; + ctxt->client_princ = client_princ; + ctxt->client_cc = client_cc; ++#ifdef WITH_SASL + ctxt->extern_cert = extern_cert; + ctxt->extern_key = extern_key; ++#endif + + debug(logopt, MODPREFIX + "ldap authentication configured with the following options:"); +@@ -1127,7 +1134,6 @@ out: + + return ret; + } +-#endif + + /* + * Take an input string as specified in the master map, and break it +@@ -1390,10 +1396,12 @@ static void free_context(struct lookup_c + defaults_free_searchdns(ctxt->sdns); + if (ctxt->dclist) + free_dclist(ctxt->dclist); ++#ifdef WITH_SASL + if (ctxt->extern_cert) + free(ctxt->extern_cert); + if (ctxt->extern_key) + free(ctxt->extern_key); ++#endif + free(ctxt); + + return; diff --git a/SOURCES/autofs-5.0.7-fix-crash-due-to-thread-unsafe-use-of-libldap.patch b/SOURCES/autofs-5.0.7-fix-crash-due-to-thread-unsafe-use-of-libldap.patch new file mode 100644 index 0000000..0de22a3 --- /dev/null +++ b/SOURCES/autofs-5.0.7-fix-crash-due-to-thread-unsafe-use-of-libldap.patch @@ -0,0 +1,117 @@ +autofs-5.0.7 - fix crash due to thread unsafe use of libldap + +From: Leonardo Chiquitto + +Add locking around LDAP initialization calls + +To prevent corruption inside SSL and LDAP libraries, it's necessary to +serialize all calls to functions that initialize LDAP contexts. + +How to reproduce the problem: + +- Setup an LDAP server with SSL/TLS support enabled +- Configure AutoFS to fetch the maps from LDAP +- Make sure the OpenLDAP client library is configured to use SSL + connections and "usetls" is set to yes in autofs_ldap_auth.conf. + +In one directory handled by AutoFS (an indirect mount point), trigger in +parallel some dozens of invalid mounts (ie, try to access keys that do not +exist in the AutoFS map). Repeat until it crashes. + +Here it always crashes in less than 20 minutes, normally inside OpenSSL. +Core dump inspection shows that internal SSL structures are corrupted, +with function pointers pointing to random addresses. + +Trying to find similar reports on the web, I found this email from an +OpenLDAP developer (partial quote, emphasis mine) [1]: + +"As far as I know, libldap is thread safe in the sense that multiple +threads can use separate LDAP* handles without running into concurrency +issues; *except for library initialization*, all accesses to common data +(i.e. global variables) is read-only." + +[1]http://www.openldap.org/cgi-bin/wilma_hiliter/openldap-software/200606/msg00252.html + +AutoFS implements no locking around LDAP initialization libraries and +it's quite common to see multiple threads executing ldap_initialize() +or ldap_start_tls_s() at the same time. +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 35 ++++++++++++++++++++++++++++++++++- + 2 files changed, 35 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -105,6 +105,7 @@ + - fix incorrect append options description in README.v5-release. + - fix mistake in assignment. + - use open(2) instead of access(2) to trigger dependent mounts. ++- fix crash due to thread unsafe use of libldap. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -52,6 +52,12 @@ static struct ldap_schema common_schema[ + }; + static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema); + ++/* ++ * Initialization of LDAP and OpenSSL must be always serialized to ++ * avoid corruption of context structures inside these libraries. ++ */ ++pthread_mutex_t ldapinit_mutex = PTHREAD_MUTEX_INITIALIZER; ++ + struct ldap_search_params { + struct autofs_point *ap; + LDAP *ldap; +@@ -138,6 +144,22 @@ int ldap_parse_page_control(LDAP *ldap, + } + #endif /* HAVE_LDAP_PARSE_PAGE_CONTROL */ + ++static void ldapinit_mutex_lock(void) ++{ ++ int status = pthread_mutex_lock(&ldapinit_mutex); ++ if (status) ++ fatal(status); ++ return; ++} ++ ++static void ldapinit_mutex_unlock(void) ++{ ++ int status = pthread_mutex_unlock(&ldapinit_mutex); ++ if (status) ++ fatal(status); ++ return; ++} ++ + static void uris_mutex_lock(struct lookup_context *ctxt) + { + int status = pthread_mutex_lock(&ctxt->uris_mutex); +@@ -198,7 +220,7 @@ int unbind_ldap_connection(unsigned logo + return rv; + } + +-LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt) ++LDAP *__init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt) + { + LDAP *ldap = NULL; + struct timeval timeout = { ctxt->timeout, 0 }; +@@ -276,6 +298,17 @@ LDAP *init_ldap_connection(unsigned logo + + return ldap; + } ++ ++LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt) ++{ ++ LDAP *ldap; ++ ++ ldapinit_mutex_lock(); ++ ldap = __init_ldap_connection(logopt, uri, ctxt); ++ ldapinit_mutex_unlock(); ++ ++ return ldap; ++} + + static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key) + { diff --git a/SOURCES/autofs-5.0.7-setup-program-map-env-from-macro-table.patch b/SOURCES/autofs-5.0.7-setup-program-map-env-from-macro-table.patch new file mode 100644 index 0000000..039bc9e --- /dev/null +++ b/SOURCES/autofs-5.0.7-setup-program-map-env-from-macro-table.patch @@ -0,0 +1,125 @@ +autofs-5.0.7 - setup program map env from macro table + +From: Ian Kent + +The ability to pass parameters to program maps, in some way, is needed. +Standard autofs specifies that program maps have one argument so passing +parameters as arguments shouldn't be done. + +This patch sets the existing macro table definitions (for both global and +local table) as environment variables before calling the map. The values +are not checked after return so, at this stage, program maps can't change +macro definitions. +--- + CHANGELOG | 1 + + include/macros.h | 1 + + lib/macros.c | 28 ++++++++++++++++++++++++++++ + modules/lookup_program.c | 20 ++++++++++++++++++++ + 4 files changed, 50 insertions(+) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -76,6 +76,7 @@ + - fix options compare. + - fix fix options compare. + - fix max() declaration. ++- setup program map env from macro table. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/include/macros.h ++++ autofs-5.0.7/include/macros.h +@@ -40,5 +40,6 @@ void macro_free_global_table(void); + void macro_free_table(struct substvar *table); + const struct substvar * + macro_findvar(const struct substvar *table, const char *str, int len); ++void macro_setenv(struct substvar *table); + + #endif +--- autofs-5.0.7.orig/lib/macros.c ++++ autofs-5.0.7/lib/macros.c +@@ -421,3 +421,31 @@ macro_findvar(const struct substvar *tab + return NULL; + } + ++/* Set environment from macro variable table */ ++void macro_setenv(struct substvar *table) ++{ ++ const struct substvar *sv = system_table; ++ const struct substvar *lv = table; ++ ++ /* ++ * First set environment from global table, matching local ++ * variables will overwrite these. ++ */ ++ while (sv) { ++ if (sv->def) ++ setenv(sv->def, sv->val, 1); ++ sv = sv->next; ++ } ++ ++ error(LOGOPT_ANY, "table %p", table); ++ dump_table(table); ++ ++ /* Next set environment from the local table */ ++ while (lv) { ++ if (lv->def) ++ setenv(lv->def, lv->val, 1); ++ lv = lv->next; ++ } ++ ++ return; ++} +--- autofs-5.0.7.orig/modules/lookup_program.c ++++ autofs-5.0.7/modules/lookup_program.c +@@ -36,9 +36,17 @@ + + struct lookup_context { + const char *mapname; ++ char *mapfmt; + struct parse_mod *parse; + }; + ++struct parse_context { ++ char *optstr; /* Mount options */ ++ char *macros; /* Map wide macro defines */ ++ struct substvar *subst; /* $-substitutions */ ++ int slashify_colons; /* Change colons to slashes? */ ++}; ++ + int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */ + + int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context) +@@ -79,6 +87,8 @@ int lookup_init(const char *mapfmt, int + if (!mapfmt) + mapfmt = MAPFMT_DEFAULT; + ++ ctxt->mapfmt = strdup(mapfmt); ++ + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parse) { + logmsg(MODPREFIX "failed to open parse context"); +@@ -255,6 +265,14 @@ int lookup_mount(struct autofs_point *ap + warn(ap->logopt, + MODPREFIX "failed to set PWD to %s for map %s", + ap->path, ctxt->mapname); ++ /* ++ * MAPFMT_DEFAULT must be "sun" for ->parse_init() to have setup ++ * the macro table. ++ */ ++ if (ctxt->mapfmt && strcmp(ctxt->mapfmt, "MAPFMT_DEFAULT")) { ++ struct parse_context *pctxt = (struct parse_context *) ctxt->parse->context; ++ macro_setenv(pctxt->subst); ++ } + execl(ctxt->mapname, ctxt->mapname, name, NULL); + _exit(255); /* execl() failed */ + } +@@ -448,6 +466,8 @@ int lookup_done(void *context) + { + struct lookup_context *ctxt = (struct lookup_context *) context; + int rv = close_parse(ctxt->parse); ++ if (ctxt->mapfmt) ++ free(ctxt->mapfmt); + free(ctxt); + return rv; + } diff --git a/SOURCES/autofs-5.0.8-add-negative-cache-lookup-to-hesiod-lookup.patch b/SOURCES/autofs-5.0.8-add-negative-cache-lookup-to-hesiod-lookup.patch new file mode 100644 index 0000000..2e5b90f --- /dev/null +++ b/SOURCES/autofs-5.0.8-add-negative-cache-lookup-to-hesiod-lookup.patch @@ -0,0 +1,89 @@ +autofs-5.0.8 - add negative cache lookup to hesiod lookup + +From: Ian Kent + +Warning, this is completely untested. + +I don't have a hesiod test environment so I can't test this at all. +If we do in fact have hesiod users then I'll need to work with them +to fix any reported problems. +--- + CHANGELOG | 1 + + modules/lookup_hesiod.c | 39 ++++++++++++++++++++++++++++++++++++++- + 2 files changed, 39 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -91,6 +91,7 @@ + - fix bad mkdir permission on create. + - fix macro_addvar() and move init to main thread. + - change walk_tree() to take ap. ++- add negative cache lookup to hesiod lookup. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_hesiod.c ++++ autofs-5.0.7/modules/lookup_hesiod.c +@@ -99,10 +99,11 @@ int lookup_read_map(struct autofs_point + */ + int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) + { ++ struct lookup_context *ctxt = (struct lookup_context *) context; + struct map_source *source; + struct mapent_cache *mc; ++ struct mapent *me; + char **hes_result; +- struct lookup_context *ctxt = (struct lookup_context *) context; + int status, rv; + char **record, *best_record = NULL, *p; + int priority, lowest_priority = INT_MAX; +@@ -117,6 +118,32 @@ int lookup_mount(struct autofs_point *ap + MODPREFIX "looking up root=\"%s\", name=\"%s\"", + ap->path, name); + ++ /* Check if we recorded a mount fail for this key anywhere */ ++ me = lookup_source_mapent(ap, name, LKP_DISTINCT); ++ if (me) { ++ if (me->status >= time(NULL)) { ++ cache_unlock(me->mc); ++ return NSS_STATUS_NOTFOUND; ++ } else { ++ struct mapent_cache *smc = me->mc; ++ struct mapent *sme; ++ ++ if (me->mapent) ++ cache_unlock(smc); ++ else { ++ cache_unlock(smc); ++ cache_writelock(smc); ++ sme = cache_lookup_distinct(smc, name); ++ /* Negative timeout expired for non-existent entry. */ ++ if (sme && !sme->mapent) { ++ if (cache_pop_mapent(sme) == CHE_FAIL) ++ cache_delete(smc, name); ++ } ++ cache_unlock(smc); ++ } ++ } ++ } ++ + chdir("/"); /* If this is not here the filesystem stays + busy, for some reason... */ + +@@ -171,6 +198,16 @@ int lookup_mount(struct autofs_point *ap + if (status) + fatal(status); + ++ if (rv) { ++ /* Don't update negative cache when re-connecting */ ++ if (ap->flags & MOUNT_FLAG_REMOUNT) ++ return NSS_STATUS_TRYAGAIN; ++ cache_writelock(mc); ++ cache_update_negative(mc, source, name, ap->negative_timeout); ++ cache_unlock(mc); ++ return NSS_STATUS_TRYAGAIN; ++ } ++ + /* + * Unavailable due to error such as module load fail + * or out of memory, etc. diff --git a/SOURCES/autofs-5.0.8-amd-lookup-update-lookup-hesiod-to-handle-amd-keys.patch b/SOURCES/autofs-5.0.8-amd-lookup-update-lookup-hesiod-to-handle-amd-keys.patch new file mode 100644 index 0000000..e14ea19 --- /dev/null +++ b/SOURCES/autofs-5.0.8-amd-lookup-update-lookup-hesiod-to-handle-amd-keys.patch @@ -0,0 +1,406 @@ +autofs-5.0.8 - amd lookup update lookup hesiod to handle amd keys + +From: Ian Kent + +Warning, this is completely untested. + +I don't have a hesiod test environment so I can't test this at all. +If we do in fact have hesiod users then I'll need to work with them +to fix any reported problems. +--- + modules/lookup_hesiod.c | 330 +++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 270 insertions(+), 60 deletions(-) + +--- autofs-5.0.7.orig/modules/lookup_hesiod.c ++++ autofs-5.0.7/modules/lookup_hesiod.c +@@ -20,12 +20,15 @@ + #include "automount.h" + #include "nsswitch.h" + +-#define MAPFMT_DEFAULT "hesiod" ++#define MAPFMT_DEFAULT "hesiod" ++#define AMD_MAP_PREFIX "hesiod." ++#define AMD_MAP_PREFIX_LEN 7 + + #define MODPREFIX "lookup(hesiod): " + #define HESIOD_LEN 512 + + struct lookup_context { ++ const char *mapname; + struct parse_mod *parser; + void *hesiod_context; + }; +@@ -50,6 +53,7 @@ int lookup_init(const char *mapfmt, int + logerr(MODPREFIX "malloc: %s", estr); + return 1; + } ++ memset(ctxt, 0, sizeof(struct lookup_context)); + + /* Initialize the resolver. */ + res_init(); +@@ -66,6 +70,20 @@ int lookup_init(const char *mapfmt, int + if (!mapfmt) + mapfmt = MAPFMT_DEFAULT; + ++ if (!strcmp(mapfmt, "amd")) { ++ /* amd formated hesiod maps have a map name */ ++ const char *mapname = argv[0]; ++ if (strncmp(mapname, AMD_MAP_PREFIX, AMD_MAP_PREFIX_LEN)) { ++ logerr(MODPREFIX ++ "incorrect prefix for hesiod map %s", mapname); ++ free(ctxt); ++ return 1; ++ } ++ ctxt->mapname = mapname; ++ argc--; ++ argv++; ++ } ++ + /* Open the parser, if we can. */ + ctxt->parser = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parser) { +@@ -97,16 +115,203 @@ int lookup_read_map(struct autofs_point + * it's an ERR filesystem, it's an error message we should log. Otherwise, + * assume it's something we know how to deal with already (generic). + */ ++static int lookup_one(struct autofs_point *ap, ++ struct map_source *source, ++ const char *key, int key_len, ++ struct lookup_context *ctxt) ++{ ++ struct mapent_cache *mc; ++ char **hes_result; ++ char **record, *best_record = NULL, *p; ++ int priority, lowest_priority = INT_MAX; ++ int ret, status; ++ ++ mc = source->mc; ++ ++ status = pthread_mutex_lock(&hesiod_mutex); ++ if (status) ++ fatal(status); ++ ++ hes_result = hesiod_resolve(ctxt->hesiod_context, key, "filsys"); ++ if (!hes_result || !hes_result[0]) { ++ int err = errno; ++ error(ap->logopt, ++ MODPREFIX "key \"%s\" not found in map", key); ++ status = pthread_mutex_unlock(&hesiod_mutex); ++ if (status) ++ fatal(status); ++ if (err == HES_ER_NOTFOUND) ++ return CHE_MISSING; ++ else ++ return CHE_FAIL; ++ } ++ ++ /* autofs doesn't support falling back to alternate records, so just ++ find the record with the lowest priority and hope it works. ++ -- Aaron Ucko 2002-03-11 */ ++ for (record = hes_result; *record; ++record) { ++ p = strrchr(*record, ' '); ++ if ( p && isdigit(p[1]) ) { ++ priority = atoi(p+1); ++ } else { ++ priority = INT_MAX - 1; ++ } ++ if (priority < lowest_priority) { ++ lowest_priority = priority; ++ best_record = *record; ++ } ++ } ++ ++ cache_writelock(mc); ++ ret = cache_update(mc, source, key, best_record, time(NULL)); ++ cache_unlock(mc); ++ if (ret == CHE_FAIL) { ++ hesiod_free_list(ctxt->hesiod_context, hes_result); ++ status = pthread_mutex_unlock(&hesiod_mutex); ++ if (status) ++ fatal(status); ++ return ret; ++ } ++ ++ debug(ap->logopt, ++ MODPREFIX "lookup for \"%s\" gave \"%s\"", ++ key, best_record); ++ ++ hesiod_free_list(ctxt->hesiod_context, hes_result); ++ ++ status = pthread_mutex_unlock(&hesiod_mutex); ++ if (status) ++ fatal(status); ++ ++ return ret; ++} ++ ++static int lookup_one_amd(struct autofs_point *ap, ++ struct map_source *source, ++ const char *key, int key_len, ++ struct lookup_context *ctxt) ++{ ++ struct mapent_cache *mc; ++ char *hesiod_base; ++ char **hes_result; ++ char *lkp_key; ++ int status, ret; ++ ++ mc = source->mc; ++ ++ hesiod_base = conf_amd_get_hesiod_base(); ++ if (!hesiod_base) ++ return CHE_FAIL; ++ ++ lkp_key = malloc(key_len + strlen(ctxt->mapname) - 7 + 2); ++ if (!lkp_key) { ++ free(hesiod_base); ++ return CHE_FAIL; ++ } ++ ++ strcpy(lkp_key, key); ++ strcat(lkp_key, "."); ++ strcat(lkp_key, ctxt->mapname + AMD_MAP_PREFIX_LEN); ++ ++ status = pthread_mutex_lock(&hesiod_mutex); ++ if (status) ++ fatal(status); ++ ++ hes_result = hesiod_resolve(ctxt->hesiod_context, lkp_key, hesiod_base); ++ if (!hes_result || !hes_result[0]) { ++ int err = errno; ++ if (err == HES_ER_NOTFOUND) ++ ret = CHE_MISSING; ++ else ++ ret = CHE_FAIL; ++ goto done; ++ } ++ ++ cache_writelock(mc); ++ ret = cache_update(mc, source, lkp_key, *hes_result, time(NULL)); ++ cache_unlock(mc); ++ ++ if (hes_result) ++ hesiod_free_list(ctxt->hesiod_context, hes_result); ++done: ++ free(lkp_key); ++ ++ status = pthread_mutex_unlock(&hesiod_mutex); ++ if (status) ++ fatal(status); ++ ++ return ret; ++} ++ ++static int match_amd_key(struct autofs_point *ap, ++ struct map_source *source, ++ const char *key, int key_len, ++ struct lookup_context *ctxt) ++{ ++ char buf[MAX_ERR_BUF]; ++ char *lkp_key; ++ char *prefix; ++ int ret; ++ ++ ret = lookup_one_amd(ap, source, key, key_len, ctxt); ++ if (ret == CHE_OK || ret == CHE_UPDATED) ++ return ret; ++ ++ lkp_key = strdup(key); ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "strdup: %s", estr); ++ return CHE_FAIL; ++ } ++ ++ ret = CHE_MISSING; ++ ++ /* ++ * Now strip successive directory components and try a ++ * match against map entries ending with a wildcard and ++ * finally try the wilcard entry itself. ++ */ ++ while ((prefix = strrchr(lkp_key, '/'))) { ++ char *match; ++ size_t len; ++ *prefix = '\0'; ++ len = strlen(lkp_key) + 3; ++ match = malloc(len); ++ if (!match) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ ret = CHE_FAIL; ++ goto done; ++ } ++ len--; ++ strcpy(match, lkp_key); ++ strcat(match, "/*"); ++ ret = lookup_one_amd(ap, source, match, len, ctxt); ++ free(match); ++ if (ret == CHE_OK || ret == CHE_UPDATED) ++ goto done; ++ } ++ ++ /* Lastly try the wildcard */ ++ ret = lookup_one_amd(ap, source, "*", 1, ctxt); ++done: ++ free(lkp_key); ++ return ret; ++} ++ + int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) + { + struct lookup_context *ctxt = (struct lookup_context *) context; +- struct map_source *source; + struct mapent_cache *mc; ++ char buf[MAX_ERR_BUF]; ++ struct map_source *source; + struct mapent *me; +- char **hes_result; +- int status, rv; +- char **record, *best_record = NULL, *p; +- int priority, lowest_priority = INT_MAX; ++ char key[KEY_MAX_LEN + 1]; ++ size_t key_len; ++ char *lkp_key; ++ size_t len; ++ char *mapent; ++ int rv; + + source = ap->entry->current; + ap->entry->current = NULL; +@@ -118,6 +323,19 @@ int lookup_mount(struct autofs_point *ap + MODPREFIX "looking up root=\"%s\", name=\"%s\"", + ap->path, name); + ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { ++ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); ++ if (key_len > KEY_MAX_LEN) ++ return NSS_STATUS_NOTFOUND; ++ } else { ++ key_len = expandamdent(name, NULL, NULL); ++ if (key_len > KEY_MAX_LEN) ++ return NSS_STATUS_NOTFOUND; ++ expandamdent(name, key, NULL); ++ key[key_len] = '\0'; ++ debug(ap->logopt, MODPREFIX "expanded key: \"%s\"", key); ++ } ++ + /* Check if we recorded a mount fail for this key anywhere */ + me = lookup_source_mapent(ap, name, LKP_DISTINCT); + if (me) { +@@ -144,69 +362,61 @@ int lookup_mount(struct autofs_point *ap + } + } + +- chdir("/"); /* If this is not here the filesystem stays +- busy, for some reason... */ +- +- status = pthread_mutex_lock(&hesiod_mutex); +- if (status) +- fatal(status); +- +- hes_result = hesiod_resolve(ctxt->hesiod_context, name, "filsys"); +- if (!hes_result || !hes_result[0]) { +- /* Note: it is not clear to me how to distinguish between +- * the "no search results" case and other failures. --JM */ +- error(ap->logopt, +- MODPREFIX "key \"%s\" not found in map", name); +- status = pthread_mutex_unlock(&hesiod_mutex); +- if (status) +- fatal(status); +- return NSS_STATUS_NOTFOUND; ++ /* If this is not here the filesystem stays busy, for some reason... */ ++ if (chdir("/")) ++ warn(ap->logopt, ++ MODPREFIX "failed to set working directory to \"/\""); ++ ++ len = key_len; ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) ++ lkp_key = strdup(key); ++ else { ++ rv = lookup_one_amd(ap, source, "/defaults", 9, ctxt); ++ if (rv == CHE_FAIL) ++ warn(ap->logopt, ++ MODPREFIX "failed to lookup \"/defaults\" entry"); ++ ++ if (!ap->pref) ++ lkp_key = strdup(key); ++ else { ++ len += strlen(ap->pref); ++ lkp_key = malloc(len + 1); ++ if (lkp_key) { ++ strcpy(lkp_key, ap->pref); ++ strcat(lkp_key, name); ++ } ++ } + } + +- /* autofs doesn't support falling back to alternate records, so just +- find the record with the lowest priority and hope it works. +- -- Aaron Ucko 2002-03-11 */ +- for (record = hes_result; *record; ++record) { +- p = strrchr(*record, ' '); +- if ( p && isdigit(p[1]) ) { +- priority = atoi(p+1); +- } else { +- priority = INT_MAX - 1; +- } +- if (priority < lowest_priority) { +- lowest_priority = priority; +- best_record = *record; +- } ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, "malloc: %s", estr); ++ return NSS_STATUS_UNKNOWN; + } + +- cache_writelock(mc); +- rv = cache_update(mc, source, name, best_record, time(NULL)); +- cache_unlock(mc); +- if (rv == CHE_FAIL) +- return NSS_STATUS_UNAVAIL; ++ if (source->flags & MAP_FLAG_FORMAT_AMD) ++ rv = match_amd_key(ap, source, lkp_key, len, ctxt); ++ else ++ rv = lookup_one(ap, source, lkp_key, len, ctxt); + +- debug(ap->logopt, +- MODPREFIX "lookup for \"%s\" gave \"%s\"", +- name, best_record); ++ if (rv == CHE_FAIL) { ++ free(lkp_key); ++ return NSS_STATUS_UNAVAIL; ++ } + +- rv = ctxt->parser->parse_mount(ap, name, name_len, best_record, +- ctxt->parser->context); ++ me = match_cached_key(ap, MODPREFIX, source, lkp_key); ++ free(lkp_key); ++ if (!me) ++ return NSS_STATUS_NOTFOUND; + +- hesiod_free_list(ctxt->hesiod_context, hes_result); ++ if (!me->mapent) ++ return NSS_STATUS_UNAVAIL; + +- status = pthread_mutex_unlock(&hesiod_mutex); +- if (status) +- fatal(status); ++ mapent = strdup(me->mapent); + +- if (rv) { +- /* Don't update negative cache when re-connecting */ +- if (ap->flags & MOUNT_FLAG_REMOUNT) +- return NSS_STATUS_TRYAGAIN; +- cache_writelock(mc); +- cache_update_negative(mc, source, name, ap->negative_timeout); +- cache_unlock(mc); +- return NSS_STATUS_TRYAGAIN; +- } ++ rv = ctxt->parser->parse_mount(ap, key, key_len, ++ mapent, ctxt->parser->context); ++ free(mapent); + + /* + * Unavailable due to error such as module load fail diff --git a/SOURCES/autofs-5.0.8-amd-lookup-update-lookup-ldap-to-handle-amd-keys.patch b/SOURCES/autofs-5.0.8-amd-lookup-update-lookup-ldap-to-handle-amd-keys.patch new file mode 100644 index 0000000..28f6816 --- /dev/null +++ b/SOURCES/autofs-5.0.8-amd-lookup-update-lookup-ldap-to-handle-amd-keys.patch @@ -0,0 +1,935 @@ +autofs-5.0.8 - amd lookup update lookup ldap to handle amd keys + +From: Ian Kent + + +--- + include/lookup_ldap.h | 3 + modules/lookup_ldap.c | 707 +++++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 651 insertions(+), 59 deletions(-) + +--- autofs-5.0.7.orig/include/lookup_ldap.h ++++ autofs-5.0.7/include/lookup_ldap.h +@@ -36,6 +36,7 @@ struct ldap_searchdn { + + struct lookup_context { + char *mapname; ++ unsigned int format; + + char *server; + int port; +@@ -43,6 +44,8 @@ struct lookup_context { + char *qdn; + unsigned int timeout; + unsigned int network_timeout; ++ unsigned long timestamp; ++ unsigned int check_defaults; + + /* LDAP version 2 or 3 */ + int version; +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #define MODULE_LOOKUP + #include "automount.h" +@@ -52,6 +53,14 @@ static struct ldap_schema common_schema[ + }; + static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema); + ++static struct ldap_schema amd_timestamp = { ++ "madmap", "amdmapName", "amdmapTimestamp", NULL, "amdmapTimestamp" ++}; ++ ++static struct ldap_schema amd_schema = { ++ "amdmap", "amdmapName", "amdmap", "amdmapKey", "amdmapValue" ++}; ++ + /* + * Initialization and de-initialization of LDAP and OpenSSL must be + * always serialized to avoid corruption of context structures inside +@@ -62,6 +71,7 @@ pthread_mutex_t ldapinit_mutex = PTHREAD + struct ldap_search_params { + struct autofs_point *ap; + LDAP *ldap; ++ char *base; + char *query, **attrs; + struct berval *cookie; + ber_int_t pageSize; +@@ -531,6 +541,16 @@ static int find_query_dn(unsigned logopt + if (ctxt->schema) + return 0; + ++ if (ctxt->format & MAP_FLAG_FORMAT_AMD) { ++ schema = alloc_common_schema(&amd_schema); ++ if (!schema) { ++ error(logopt, MODPREFIX "failed to allocate schema"); ++ return 0; ++ } ++ ctxt->schema = schema; ++ return 1; ++ } ++ + for (i = 0; i < common_schema_count; i++) { + const char *class = common_schema[i].map_class; + const char *key = common_schema[i].map_attr; +@@ -587,8 +607,10 @@ static int do_bind(unsigned logopt, LDAP + + if (!ctxt->cur_host) { + ctxt->cur_host = nhost; +- /* Check if schema defined in conf first time only */ +- ctxt->schema = defaults_get_schema(); ++ if (!(ctxt->format & MAP_FLAG_FORMAT_AMD)) { ++ /* Check if schema defined in conf first time only */ ++ ctxt->schema = defaults_get_schema(); ++ } + } else { + /* If connection host has changed update */ + if (strcmp(ctxt->cur_host, nhost)) { +@@ -614,7 +636,7 @@ static int do_bind(unsigned logopt, LDAP + MODPREFIX "failed to find valid query dn"); + return 0; + } +- } else { ++ } else if (!(ctxt->format & MAP_FLAG_FORMAT_AMD)) { + const char *class = ctxt->schema->map_class; + const char *key = ctxt->schema->map_attr; + if (!get_query_dn(logopt, ldap, ctxt, class, key)) { +@@ -648,6 +670,126 @@ static LDAP *do_connect(unsigned logopt, + return ldap; + } + ++static unsigned long get_amd_timestamp(struct lookup_context *ctxt) ++{ ++ LDAP *ldap; ++ LDAPMessage *result = NULL, *e; ++ char *query; ++ int scope = LDAP_SCOPE_SUBTREE; ++ char *map, *class, *value; ++ char *attrs[2]; ++ struct berval **bvValues; ++ unsigned long timestamp = 0; ++ int rv, l, ql; ++ ++ ldap = do_connect(LOGOPT_ANY, ctxt->server, ctxt); ++ if (!ldap) ++ return 0; ++ ++ map = amd_timestamp.map_attr; ++ class = amd_timestamp.entry_class; ++ value = amd_timestamp.value_attr; ++ ++ attrs[0] = value; ++ attrs[1] = NULL; ++ ++ /* Build a query string. */ ++ l = strlen(class) + ++ strlen(map) + strlen(ctxt->mapname) + 21; ++ ++ query = malloc(l); ++ if (query == NULL) { ++ char buf[MAX_ERR_BUF]; ++ char *estr = strerror_r(errno, buf, sizeof(buf)); ++ crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ return 0; ++ } ++ ++ /* ++ * Look for an entry in class under ctxt-base ++ * whose entry is equal to qKey. ++ */ ++ ql = sprintf(query, "(&(objectclass=%s)(%s=%s))", ++ class, map, ctxt->mapname); ++ if (ql >= l) { ++ error(LOGOPT_ANY, ++ MODPREFIX "error forming query string"); ++ free(query); ++ return 0; ++ } ++ ++ rv = ldap_search_s(ldap, ctxt->base, scope, query, attrs, 0, &result); ++ if ((rv != LDAP_SUCCESS) || !result) { ++ crit(LOGOPT_ANY, MODPREFIX "timestamp query failed %s", query); ++ unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt); ++ if (result) ++ ldap_msgfree(result); ++ free(query); ++ return 0; ++ } ++ ++ e = ldap_first_entry(ldap, result); ++ if (!e) { ++ debug(LOGOPT_ANY, ++ MODPREFIX "got answer, but no entry for timestamp"); ++ ldap_msgfree(result); ++ unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt); ++ free(query); ++ return CHE_MISSING; ++ } ++ ++ while (e) { ++ char *v_val; ++ char *endptr; ++ ++ bvValues = ldap_get_values_len(ldap, e, value); ++ if (!bvValues || !*bvValues) { ++ debug(LOGOPT_ANY, ++ MODPREFIX "no value found in timestamp"); ++ goto next; ++ } ++ ++ /* There should be one value for a timestamp */ ++ v_val = bvValues[0]->bv_val; ++ ++ timestamp = strtol(v_val, &endptr, 0); ++ if ((errno == ERANGE && ++ (timestamp == LONG_MAX || timestamp == LONG_MIN)) || ++ (errno != 0 && timestamp == 0)) { ++ debug(LOGOPT_ANY, ++ MODPREFIX "invalid value in timestamp"); ++ free(query); ++ return 0; ++ } ++ ++ if (endptr == v_val) { ++ debug(LOGOPT_ANY, ++ MODPREFIX "no digits found in timestamp"); ++ free(query); ++ return 0; ++ } ++ ++ if (*endptr != '\0') { ++ warn(LOGOPT_ANY, MODPREFIX ++ "characters found after number: %s", endptr); ++ warn(LOGOPT_ANY, ++ MODPREFIX "timestamp may be invalid"); ++ } ++ ++ ldap_value_free_len(bvValues); ++ break; ++next: ++ ldap_value_free_len(bvValues); ++ e = ldap_next_entry(ldap, e); ++ } ++ ++ ldap_msgfree(result); ++ unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt); ++ free(query); ++ ++ return timestamp; ++} ++ + static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_context *ctxt) + { + LDAP *ldap; +@@ -1215,7 +1357,7 @@ static int parse_server_string(unsigned + const char *q = NULL; + + /* Isolate the server(s). */ +- if ((q = strchr(s, '/'))) { ++ if ((q = strchr(s, '/')) || (q = strchr(s, '\0'))) { + l = q - s; + if (*proto) { + al_len = l + strlen(proto) + 2; +@@ -1318,8 +1460,7 @@ static int parse_server_string(unsigned + ptr += l + 1; + } + +- /* TODO: why did I do this - how can the map name "and" base dn be missing? */ +- if (!ptr) ++ if (!ptr || ctxt->format & MAP_FLAG_FORMAT_AMD) + goto done; + + /* +@@ -1505,36 +1646,83 @@ int lookup_init(const char *mapfmt, int + /* If a map type isn't explicitly given, parse it like sun entries. */ + if (mapfmt == NULL) + mapfmt = MAPFMT_DEFAULT; +- +- /* +- * Parse out the server name and base dn, and fill them +- * into the proper places in the lookup context structure. +- */ +- if (!parse_server_string(LOGOPT_NONE, argv[0], ctxt)) { +- error(LOGOPT_ANY, MODPREFIX "cannot parse server string"); +- free_context(ctxt); +- return 1; ++ if (!strcmp(mapfmt, "amd")) { ++ ctxt->format = MAP_FLAG_FORMAT_AMD; ++ ctxt->check_defaults = 1; + } + +- if (!ctxt->base) +- ctxt->sdns = defaults_get_searchdns(); +- + ctxt->timeout = defaults_get_ldap_timeout(); + ctxt->network_timeout = defaults_get_ldap_network_timeout(); + +- if (!ctxt->server) { +- struct list_head *uris = defaults_get_uris(); +- if (uris) { +- validate_uris(uris); +- if (!list_empty(uris)) +- ctxt->uris = uris; +- else { +- error(LOGOPT_ANY, +- "no valid uris found in config list" +- ", using default system config"); +- free(uris); ++ if (!(ctxt->format & MAP_FLAG_FORMAT_AMD)) { ++ /* ++ * Parse out the server name and base dn, and fill them ++ * into the proper places in the lookup context structure. ++ */ ++ if (!parse_server_string(LOGOPT_NONE, argv[0], ctxt)) { ++ error(LOGOPT_ANY, MODPREFIX "cannot parse server string"); ++ free_context(ctxt); ++ return 1; ++ } ++ ++ if (!ctxt->base) ++ ctxt->sdns = defaults_get_searchdns(); ++ ++ if (!ctxt->server) { ++ struct list_head *uris = defaults_get_uris(); ++ if (uris) { ++ validate_uris(uris); ++ if (!list_empty(uris)) ++ ctxt->uris = uris; ++ else { ++ error(LOGOPT_ANY, MODPREFIX ++ "no valid uris found in config list" ++ ", using default system config"); ++ free(uris); ++ } + } + } ++ } else { ++ char *tmp = conf_amd_get_ldap_base(); ++ if (!tmp) { ++ error(LOGOPT_ANY, MODPREFIX "failed to get base dn"); ++ free_context(ctxt); ++ return 1; ++ } ++ ctxt->base = tmp; ++ ++ tmp = conf_amd_get_ldap_hostports(); ++ if (!tmp) { ++ error(LOGOPT_ANY, ++ MODPREFIX "failed to get ldap_hostports"); ++ free_context(ctxt); ++ return 1; ++ } ++ ++ /* ++ * Parse out the server name and port, and save them in ++ * the proper places in the lookup context structure. ++ */ ++ if (!parse_server_string(LOGOPT_NONE, tmp, ctxt)) { ++ error(LOGOPT_ANY, MODPREFIX "cannot parse server string"); ++ free_context(ctxt); ++ return 1; ++ } ++ free(tmp); ++ ++ if (!ctxt->server) { ++ error(LOGOPT_ANY, MODPREFIX "ldap_hostports not valid"); ++ free_context(ctxt); ++ return 1; ++ } ++ ++ tmp = strdup(argv[0]); ++ if (!tmp) { ++ error(LOGOPT_ANY, MODPREFIX "failed to set mapname"); ++ free_context(ctxt); ++ return 1; ++ } ++ ctxt->mapname = tmp; + } + + /* +@@ -1558,6 +1746,8 @@ int lookup_init(const char *mapfmt, int + } + #endif + ++ ctxt->timestamp = get_amd_timestamp(ctxt); ++ + /* Open the parser, if we can. */ + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parse) { +@@ -2029,7 +2219,7 @@ static int do_paged_query(struct ldap_se + if (sp->morePages == TRUE) + goto do_paged; + +- rv = ldap_search_s(sp->ldap, ctxt->qdn, scope, sp->query, sp->attrs, 0, &sp->result); ++ rv = ldap_search_s(sp->ldap, sp->base, scope, sp->query, sp->attrs, 0, &sp->result); + if ((rv != LDAP_SUCCESS) || !sp->result) { + /* + * Check for Size Limit exceeded and force run through loop +@@ -2063,7 +2253,7 @@ do_paged: + + /* Search for entries in the directory using the parmeters. */ + rv = ldap_search_ext_s(sp->ldap, +- ctxt->qdn, scope, sp->query, sp->attrs, ++ sp->base, scope, sp->query, sp->attrs, + 0, controls, NULL, NULL, 0, &sp->result); + if ((rv != LDAP_SUCCESS) && (rv != LDAP_PARTIAL_RESULTS)) { + ldap_control_free(pageControl); +@@ -2364,6 +2554,115 @@ next: + return LDAP_SUCCESS; + } + ++static int do_get_amd_entries(struct ldap_search_params *sp, ++ struct map_source *source, ++ struct lookup_context *ctxt) ++{ ++ struct autofs_point *ap = sp->ap; ++ struct mapent_cache *mc = source->mc; ++ struct berval **bvKey; ++ struct berval **bvValues; ++ LDAPMessage *e; ++ char *entry, *value; ++ int rv, ret, count; ++ ++ entry = ctxt->schema->entry_attr; ++ value = ctxt->schema->value_attr; ++ ++ e = ldap_first_entry(sp->ldap, sp->result); ++ if (!e) { ++ debug(ap->logopt, ++ MODPREFIX "query succeeded, no matches for %s", ++ sp->query); ++ ret = ldap_parse_result(sp->ldap, sp->result, ++ &rv, NULL, NULL, NULL, NULL, 0); ++ if (ret == LDAP_SUCCESS) ++ return rv; ++ else ++ return LDAP_OPERATIONS_ERROR; ++ } else ++ debug(ap->logopt, MODPREFIX "examining entries"); ++ ++ while (e) { ++ char *k_val, *v_val; ++ ber_len_t k_len; ++ char *s_key; ++ ++ bvKey = ldap_get_values_len(sp->ldap, e, entry); ++ if (!bvKey || !*bvKey) { ++ e = ldap_next_entry(sp->ldap, e); ++ if (!e) { ++ debug(ap->logopt, MODPREFIX ++ "failed to get next entry for query %s", ++ sp->query); ++ ret = ldap_parse_result(sp->ldap, ++ sp->result, &rv, ++ NULL, NULL, NULL, NULL, 0); ++ if (ret == LDAP_SUCCESS) ++ return rv; ++ else ++ return LDAP_OPERATIONS_ERROR; ++ } ++ continue; ++ } ++ ++ /* By definition keys should be unique within each map entry */ ++ k_val = NULL; ++ k_len = 0; ++ ++ count = ldap_count_values_len(bvKey); ++ if (count > 1) ++ warn(ap->logopt, MODPREFIX ++ "more than one %s, using first", entry); ++ ++ k_val = bvKey[0]->bv_val; ++ k_len = bvKey[0]->bv_len; ++ ++ bvValues = ldap_get_values_len(sp->ldap, e, value); ++ if (!bvValues || !*bvValues) { ++ debug(ap->logopt, ++ MODPREFIX "no %s defined for %s", ++ value, sp->query); ++ goto next; ++ } ++ ++ count = ldap_count_values_len(bvValues); ++ if (count > 1) ++ warn(ap->logopt, MODPREFIX ++ "more than one %s, using first", value); ++ ++ v_val = bvValues[0]->bv_val; ++ ++ /* Don't fail on "/" in key => type == 0 */ ++ s_key = sanitize_path(k_val, k_len, 0, ap->logopt); ++ if (!s_key) ++ goto next; ++ ++ cache_writelock(mc); ++ cache_update(mc, source, s_key, v_val, sp->age); ++ cache_unlock(mc); ++ ++ free(s_key); ++next: ++ ldap_value_free_len(bvValues); ++ ldap_value_free_len(bvKey); ++ e = ldap_next_entry(sp->ldap, e); ++ if (!e) { ++ debug(ap->logopt, MODPREFIX ++ "failed to get next entry for query %s", ++ sp->query); ++ ret = ldap_parse_result(sp->ldap, ++ sp->result, &rv, ++ NULL, NULL, NULL, NULL, 0); ++ if (ret == LDAP_SUCCESS) ++ return rv; ++ else ++ return LDAP_OPERATIONS_ERROR; ++ } ++ } ++ ++ return LDAP_SUCCESS; ++} + + static int read_one_map(struct autofs_point *ap, + struct map_source *source, +@@ -2419,9 +2718,14 @@ static int read_one_map(struct autofs_po + return NSS_STATUS_UNAVAIL; + } + ++ if (ctxt->format & MAP_FLAG_FORMAT_AMD) ++ sp.base = ctxt->base; ++ else ++ sp.base = ctxt->qdn; ++ + /* Look around. */ + debug(ap->logopt, +- MODPREFIX "searching for \"%s\" under \"%s\"", sp.query, ctxt->qdn); ++ MODPREFIX "searching for \"%s\" under \"%s\"", sp.query, sp.base); + + sp.cookie = NULL; + sp.pageSize = 2000; +@@ -2465,7 +2769,10 @@ static int read_one_map(struct autofs_po + return NSS_STATUS_UNAVAIL; + } + +- rv = do_get_entries(&sp, source, ctxt); ++ if (source->flags & MAP_FLAG_FORMAT_AMD) ++ rv = do_get_amd_entries(&sp, source, ctxt); ++ else ++ rv = do_get_entries(&sp, source, ctxt); + if (rv != LDAP_SUCCESS) { + ldap_msgfree(sp.result); + unbind_ldap_connection(ap->logopt, sp.ldap, ctxt); +@@ -2874,6 +3181,219 @@ next: + return ret; + } + ++static int lookup_one_amd(struct autofs_point *ap, ++ struct map_source *source, ++ char *qKey, int qKey_len, ++ struct lookup_context *ctxt) ++{ ++ struct mapent_cache *mc = source->mc; ++ LDAP *ldap; ++ LDAPMessage *result = NULL, *e; ++ char *query; ++ int scope = LDAP_SCOPE_SUBTREE; ++ char *map, *class, *entry, *value; ++ char *attrs[3]; ++ struct berval **bvKey; ++ struct berval **bvValues; ++ char buf[MAX_ERR_BUF]; ++ time_t age = time(NULL); ++ int rv, l, ql, count; ++ int ret = CHE_MISSING; ++ ++ if (ctxt == NULL) { ++ crit(ap->logopt, MODPREFIX "context was NULL"); ++ return CHE_FAIL; ++ } ++ ++ /* Initialize the LDAP context. */ ++ ldap = do_reconnect(ap->logopt, ctxt); ++ if (!ldap) ++ return CHE_UNAVAIL; ++ ++ map = ctxt->schema->map_attr; ++ class = ctxt->schema->entry_class; ++ entry = ctxt->schema->entry_attr; ++ value = ctxt->schema->value_attr; ++ ++ attrs[0] = entry; ++ attrs[1] = value; ++ attrs[2] = NULL; ++ ++ /* Build a query string. */ ++ l = strlen(class) + ++ strlen(map) + strlen(ctxt->mapname) + ++ strlen(entry) + strlen(qKey) + 24; ++ ++ query = malloc(l); ++ if (query == NULL) { ++ char *estr = strerror_r(errno, buf, sizeof(buf)); ++ crit(ap->logopt, MODPREFIX "malloc: %s", estr); ++ return CHE_FAIL; ++ } ++ ++ /* ++ * Look for an entry in class under ctxt-base ++ * whose entry is equal to qKey. ++ */ ++ ql = sprintf(query, "(&(objectclass=%s)(%s=%s)(%s=%s))", ++ class, map, ctxt->mapname, entry, qKey); ++ if (ql >= l) { ++ error(ap->logopt, ++ MODPREFIX "error forming query string"); ++ free(query); ++ return CHE_FAIL; ++ } ++ ++ debug(ap->logopt, ++ MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->base); ++ ++ rv = ldap_search_s(ldap, ctxt->base, scope, query, attrs, 0, &result); ++ if ((rv != LDAP_SUCCESS) || !result) { ++ crit(ap->logopt, MODPREFIX "query failed for %s", query); ++ unbind_ldap_connection(ap->logopt, ldap, ctxt); ++ if (result) ++ ldap_msgfree(result); ++ free(query); ++ return CHE_FAIL; ++ } ++ ++ debug(ap->logopt, ++ MODPREFIX "getting first entry for %s=\"%s\"", entry, qKey); ++ ++ e = ldap_first_entry(ldap, result); ++ if (!e) { ++ debug(ap->logopt, ++ MODPREFIX "got answer, but no entry for %s", query); ++ ldap_msgfree(result); ++ unbind_ldap_connection(ap->logopt, ldap, ctxt); ++ free(query); ++ return CHE_MISSING; ++ } ++ ++ while (e) { ++ char *k_val, *v_val; ++ ber_len_t k_len; ++ char *s_key; ++ ++ bvKey = ldap_get_values_len(ldap, e, entry); ++ if (!bvKey || !*bvKey) { ++ e = ldap_next_entry(ldap, e); ++ continue; ++ } ++ ++ /* By definition keys should be unique within each map entry */ ++ k_val = NULL; ++ k_len = 0; ++ ++ count = ldap_count_values_len(bvKey); ++ if (count > 1) ++ warn(ap->logopt, MODPREFIX ++ "more than one %s, using first", entry); ++ ++ k_val = bvKey[0]->bv_val; ++ k_len = bvKey[0]->bv_len; ++ ++ debug(ap->logopt, MODPREFIX "examining first entry"); ++ ++ bvValues = ldap_get_values_len(ldap, e, value); ++ if (!bvValues || !*bvValues) { ++ debug(ap->logopt, ++ MODPREFIX "no %s defined for %s", value, query); ++ goto next; ++ } ++ ++ count = ldap_count_values_len(bvValues); ++ if (count > 1) ++ warn(ap->logopt, MODPREFIX ++ "more than one %s, using first", value); ++ ++ /* There should be one value for a key, use first value */ ++ v_val = bvValues[0]->bv_val; ++ ++ /* Don't fail on "/" in key => type == 0 */ ++ s_key = sanitize_path(k_val, k_len, 0, ap->logopt); ++ if (!s_key) ++ goto next; ++ ++ cache_writelock(mc); ++ ret = cache_update(mc, source, s_key, v_val, age); ++ cache_unlock(mc); ++ ++ free(s_key); ++next: ++ ldap_value_free_len(bvValues); ++ ldap_value_free_len(bvKey); ++ e = ldap_next_entry(ldap, e); ++ } ++ ++ ldap_msgfree(result); ++ unbind_ldap_connection(ap->logopt, ldap, ctxt); ++ free(query); ++ ++ return ret; ++} ++ ++static int match_key(struct autofs_point *ap, ++ struct map_source *source, ++ char *key, int key_len, ++ struct lookup_context *ctxt) ++{ ++ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; ++ char buf[MAX_ERR_BUF]; ++ char *lkp_key; ++ char *prefix; ++ int ret; ++ ++ if (is_amd_format) ++ ret = lookup_one_amd(ap, source, key, key_len, ctxt); ++ else ++ ret = lookup_one(ap, source, key, key_len, ctxt); ++ ++ if (ret == CHE_OK || ret == CHE_UPDATED) ++ return ret; ++ ++ if (!is_amd_format) ++ return CHE_FAIL; ++ ++ lkp_key = strdup(key); ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "strdup: %s", estr); ++ return CHE_FAIL; ++ } ++ ++ ret = CHE_MISSING; ++ ++ /* ++ * Now strip successive directory components and try a ++ * match against map entries ending with a wildcard and ++ * finally try the wilcard entry itself. ++ */ ++ while ((prefix = strrchr(lkp_key, '/'))) { ++ char *match; ++ size_t len; ++ *prefix = '\0'; ++ len = strlen(lkp_key + 3); ++ match = malloc(len); ++ if (!match) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ ret = CHE_FAIL; ++ goto done; ++ } ++ len--; ++ strcpy(match, lkp_key); ++ strcat(match, "/*"); ++ ret = lookup_one_amd(ap, source, match, len, ctxt); ++ free(match); ++ if (ret == CHE_OK || ret == CHE_UPDATED) ++ goto done; ++ } ++done: ++ free(lkp_key); ++ return ret; ++} ++ + static int check_map_indirect(struct autofs_point *ap, + struct map_source *source, + char *key, int key_len, +@@ -2888,16 +3408,43 @@ static int check_map_indirect(struct aut + mc = source->mc; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); +- ret = lookup_one(ap, source, key, key_len, ctxt); ++ ++ pthread_mutex_lock(&ap->entry->current_mutex); ++ if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ unsigned long timestamp = get_amd_timestamp(ctxt); ++ if (timestamp > ctxt->timestamp) { ++ ctxt->timestamp = timestamp; ++ source->stale = 1; ++ ctxt->check_defaults = 1; ++ } ++ ++ if (ctxt->check_defaults) { ++ /* Check for a /defaults entry */ ++ ret = lookup_one_amd(ap, source, "/defaults", 9, ctxt); ++ if (ret == CHE_FAIL) { ++ warn(ap->logopt, MODPREFIX ++ "error getting /defaults from map %s", ++ ctxt->mapname); ++ } else ++ ctxt->check_defaults = 0; ++ } ++ } ++ pthread_mutex_unlock(&ap->entry->current_mutex); ++ ++ ret = match_key(ap, source, key, key_len, ctxt); + if (ret == CHE_FAIL) { + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_NOTFOUND; + } else if (ret == CHE_UNAVAIL) { ++ struct mapent *exists; + /* + * If the server is down and the entry exists in the cache + * and belongs to this map return success and use the entry. + */ +- struct mapent *exists = cache_lookup(mc, key); ++ if (source->flags & MAP_FLAG_FORMAT_AMD) ++ exists = match_cached_key(ap, MODPREFIX, source, key); ++ else ++ exists = cache_lookup(mc, key); + if (exists && exists->source == source) { + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_SUCCESS; +@@ -2910,24 +3457,28 @@ static int check_map_indirect(struct aut + } + pthread_setcancelstate(cur_state, NULL); + +- /* +- * Check for map change and update as needed for +- * following cache lookup. +- */ +- cache_readlock(mc); +- t_last_read = ap->exp_runfreq + 1; +- me = cache_lookup_first(mc); +- while (me) { +- if (me->source == source) { +- t_last_read = now - me->age; +- break; ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { ++ /* ++ * Check for map change and update as needed for ++ * following cache lookup. ++ */ ++ cache_readlock(mc); ++ t_last_read = ap->exp_runfreq + 1; ++ me = cache_lookup_first(mc); ++ while (me) { ++ if (me->source == source) { ++ t_last_read = now - me->age; ++ break; ++ } ++ me = cache_lookup_next(mc, me); + } +- me = cache_lookup_next(mc, me); +- } +- cache_unlock(mc); ++ cache_unlock(mc); + +- if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) +- source->stale = 1; ++ pthread_mutex_lock(&ap->entry->current_mutex); ++ if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) ++ source->stale = 1; ++ pthread_mutex_unlock(&ap->entry->current_mutex); ++ } + + cache_readlock(mc); + me = cache_lookup_distinct(mc, "*"); +@@ -2948,8 +3499,10 @@ int lookup_mount(struct autofs_point *ap + struct mapent *me; + char key[KEY_MAX_LEN + 1]; + int key_len; ++ char *lkp_key; + char *mapent = NULL; + char mapent_buf[MAPENT_MAX_LEN + 1]; ++ char buf[MAX_ERR_BUF]; + int status = 0; + int ret = 1; + +@@ -2961,9 +3514,18 @@ int lookup_mount(struct autofs_point *ap + + debug(ap->logopt, MODPREFIX "looking up %s", name); + +- key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); +- if (key_len > KEY_MAX_LEN) +- return NSS_STATUS_NOTFOUND; ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { ++ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); ++ if (key_len > KEY_MAX_LEN) ++ return NSS_STATUS_NOTFOUND; ++ } else { ++ key_len = expandamdent(name, NULL, NULL); ++ if (key_len > KEY_MAX_LEN) ++ return NSS_STATUS_NOTFOUND; ++ expandamdent(name, key, NULL); ++ key[key_len] = '\0'; ++ debug(ap->logopt, MODPREFIX "expanded key: \"%s\"", key); ++ } + + /* Check if we recorded a mount fail for this key anywhere */ + me = lookup_source_mapent(ap, key, LKP_DISTINCT); +@@ -2997,18 +3559,26 @@ int lookup_mount(struct autofs_point *ap + * we never know about it. + */ + if (ap->type == LKP_INDIRECT && *key != '/') { +- char *lkp_key; +- + cache_readlock(mc); + me = cache_lookup_distinct(mc, key); + if (me && me->multi) + lkp_key = strdup(me->multi->key); +- else ++ else if (!ap->pref) + lkp_key = strdup(key); ++ else { ++ lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1); ++ if (lkp_key) { ++ strcpy(lkp_key, ap->pref); ++ strcat(lkp_key, key); ++ } ++ } + cache_unlock(mc); + +- if (!lkp_key) ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); + return NSS_STATUS_UNKNOWN; ++ } + + status = check_map_indirect(ap, source, + lkp_key, strlen(lkp_key), ctxt); +@@ -3029,7 +3599,25 @@ int lookup_mount(struct autofs_point *ap + cache_readlock(mc); + else + cache_writelock(mc); +- me = cache_lookup(mc, key); ++ ++ if (!ap->pref) ++ lkp_key = strdup(key); ++ else { ++ lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1); ++ if (lkp_key) { ++ strcpy(lkp_key, ap->pref); ++ strcat(lkp_key, key); ++ } ++ } ++ ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ cache_unlock(mc); ++ return NSS_STATUS_UNKNOWN; ++ } ++ ++ me = match_cached_key(ap, MODPREFIX, source, lkp_key); + /* Stale mapent => check for entry in alternate source or wildcard */ + if (me && !me->mapent) { + while ((me = cache_lookup_key_next(me))) +@@ -3055,6 +3643,7 @@ int lookup_mount(struct autofs_point *ap + } + } + cache_unlock(mc); ++ free(lkp_key); + + if (!mapent) + return NSS_STATUS_TRYAGAIN; diff --git a/SOURCES/autofs-5.0.8-change-walk_tree-to-take-ap.patch b/SOURCES/autofs-5.0.8-change-walk_tree-to-take-ap.patch new file mode 100644 index 0000000..02be4cf --- /dev/null +++ b/SOURCES/autofs-5.0.8-change-walk_tree-to-take-ap.patch @@ -0,0 +1,226 @@ +autofs-5.0.8 - change walk_tree() to take ap + +From: Ian Kent + +Change walk_tree() to take an autofs_point pointer instead of +logopt. +--- + CHANGELOG | 1 + + daemon/automount.c | 49 +++++++++++++++++++++++++++++-------------------- + daemon/direct.c | 2 +- + daemon/indirect.c | 6 +++--- + include/automount.h | 4 ++-- + 5 files changed, 36 insertions(+), 26 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -90,6 +90,7 @@ + - fix master map type check. + - fix bad mkdir permission on create. + - fix macro_addvar() and move init to main thread. ++- change walk_tree() to take ap. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/automount.c ++++ autofs-5.0.7/daemon/automount.c +@@ -254,10 +254,12 @@ int rmdir_path(struct autofs_point *ap, + /* Like ftw, except fn gets called twice: before a directory is + entered, and after. If the before call returns 0, the directory + isn't entered. */ +-static int walk_tree(const char *base, int (*fn) (unsigned logopt, ++static int walk_tree(const char *base, int (*fn) (struct autofs_point *ap, + const char *file, + const struct stat * st, +- int, void *), int incl, unsigned logopt, void *arg) ++ int, void *), int incl, ++ struct autofs_point *ap, ++ void *arg) + { + char buf[PATH_MAX + 1]; + struct stat st, *pst = &st; +@@ -270,7 +272,7 @@ static int walk_tree(const char *base, i + ret = 0; + } + +- if (ret != -1 && (fn) (logopt, base, pst, 0, arg)) { ++ if (ret != -1 && (fn) (ap, base, pst, 0, arg)) { + if (S_ISDIR(st.st_mode)) { + struct dirent **de; + int n; +@@ -298,18 +300,20 @@ static int walk_tree(const char *base, i + return -1; + } + +- walk_tree(buf, fn, 1, logopt, arg); ++ walk_tree(buf, fn, 1, ap, arg); + free(de[n]); + } + free(de); + } + if (incl) +- (fn) (logopt, base, pst, 1, arg); ++ (fn) (ap, base, pst, 1, arg); + } + return 0; + } + +-static int rm_unwanted_fn(unsigned logopt, const char *file, const struct stat *st, int when, void *arg) ++static int rm_unwanted_fn(struct autofs_point *ap, ++ const char *file, const struct stat *st, ++ int when, void *arg) + { + dev_t dev = *(dev_t *) arg; + char buf[MAX_ERR_BUF]; +@@ -325,38 +329,40 @@ static int rm_unwanted_fn(unsigned logop + } + + if (lstat(file, &newst)) { +- crit(logopt, "unable to stat file, possible race condition"); ++ crit(ap->logopt, ++ "unable to stat file, possible race condition"); + return 0; + } + + if (newst.st_dev != dev) { +- crit(logopt, "file %s has the wrong device, possible race condition", ++ crit(ap->logopt, ++ "file %s has the wrong device, possible race condition", + file); + return 0; + } + + if (S_ISDIR(newst.st_mode)) { +- debug(logopt, "removing directory %s", file); ++ debug(ap->logopt, "removing directory %s", file); + if (rmdir(file)) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- warn(logopt, ++ warn(ap->logopt, + "unable to remove directory %s: %s", file, estr); + return 0; + } + } else if (S_ISREG(newst.st_mode)) { +- crit(logopt, "attempting to remove files from a mounted " ++ crit(ap->logopt, "attempting to remove files from a mounted " + "directory. file %s", file); + return 0; + } else if (S_ISLNK(newst.st_mode)) { +- debug(logopt, "removing symlink %s", file); ++ debug(ap->logopt, "removing symlink %s", file); + unlink(file); + } + return 1; + } + +-void rm_unwanted(unsigned logopt, const char *path, int incl, dev_t dev) ++void rm_unwanted(struct autofs_point *ap, const char *path, int incl) + { +- walk_tree(path, rm_unwanted_fn, incl, logopt, &dev); ++ walk_tree(path, rm_unwanted_fn, incl, ap, &ap->dev); + } + + struct counter_args { +@@ -364,7 +370,8 @@ struct counter_args { + dev_t dev; + }; + +-static int counter_fn(unsigned logopt, const char *file, const struct stat *st, int when, void *arg) ++static int counter_fn(struct autofs_point *ap, const char *file, ++ const struct stat *st, int when, void *arg) + { + struct counter_args *counter = (struct counter_args *) arg; + +@@ -378,14 +385,14 @@ static int counter_fn(unsigned logopt, c + } + + /* Count mounted filesystems and symlinks */ +-int count_mounts(unsigned logopt, const char *path, dev_t dev) ++int count_mounts(struct autofs_point *ap, const char *path, dev_t dev) + { + struct counter_args counter; + + counter.count = 0; + counter.dev = dev; + +- if (walk_tree(path, counter_fn, 0, logopt, &counter) == -1) ++ if (walk_tree(path, counter_fn, 0, ap, &counter) == -1) + return -1; + + return counter.count; +@@ -409,9 +416,9 @@ static void check_rm_dirs(struct autofs_ + (ap->state == ST_SHUTDOWN_PENDING || + ap->state == ST_SHUTDOWN_FORCE || + ap->state == ST_SHUTDOWN)) +- rm_unwanted(ap->logopt, path, incl, ap->dev); ++ rm_unwanted(ap, path, incl); + else if ((ap->flags & MOUNT_FLAG_GHOST) && (ap->type == LKP_INDIRECT)) +- rm_unwanted(ap->logopt, path, 0, ap->dev); ++ rm_unwanted(ap, path, 0); + } + + /* Try to purge cache entries kept around due to existing mounts */ +@@ -553,7 +560,9 @@ int umount_multi(struct autofs_point *ap + left += umount_subtree_mounts(ap, path, is_autofs_fs); + + /* Delete detritus like unwanted mountpoints and symlinks */ +- if (left == 0 && ap->state != ST_READMAP) { ++ if (left == 0 && ++ ap->state != ST_READMAP && ++ !count_mounts(ap, path, ap->dev)) { + update_map_cache(ap, path); + check_rm_dirs(ap, path, incl); + } +--- autofs-5.0.7.orig/daemon/direct.c ++++ autofs-5.0.7/daemon/direct.c +@@ -912,7 +912,7 @@ void *expire_proc_direct(void *arg) + cache_writelock(me->mc); + if (me->ioctlfd != -1 && + fstat(me->ioctlfd, &st) != -1 && +- !count_mounts(ap->logopt, next->path, st.st_dev)) { ++ !count_mounts(ap, next->path, st.st_dev)) { + ops->close(ap->logopt, me->ioctlfd); + me->ioctlfd = -1; + cache_unlock(me->mc); +--- autofs-5.0.7.orig/daemon/indirect.c ++++ autofs-5.0.7/daemon/indirect.c +@@ -365,7 +365,7 @@ force_umount: + } else { + info(ap->logopt, "umounted indirect mount %s", mountpoint); + if (ap->submount) +- rm_unwanted(ap->logopt, mountpoint, 1, ap->dev); ++ rm_unwanted(ap, mountpoint, 1); + } + + return rv; +@@ -476,7 +476,7 @@ void *expire_proc_indirect(void *arg) + + /* Check for manual umount */ + if (fstat(me->ioctlfd, &st) == -1 || +- !count_mounts(ap->logopt, me->key, st.st_dev)) { ++ !count_mounts(ap, me->key, st.st_dev)) { + ops->close(ap->logopt, me->ioctlfd); + me->ioctlfd = -1; + } +@@ -538,7 +538,7 @@ void *expire_proc_indirect(void *arg) + * so we need to umount or unlink them here. + */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); +- retries = (count_mounts(ap->logopt, ap->path, ap->dev) + 1); ++ retries = (count_mounts(ap, ap->path, ap->dev) + 1); + while (retries--) { + ret = ops->expire(ap->logopt, ap->ioctlfd, ap->path, now); + if (ret) +--- autofs-5.0.7.orig/include/automount.h ++++ autofs-5.0.7/include/automount.h +@@ -526,8 +526,8 @@ int handle_packet_expire_indirect(struct + int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_direct_t *pkt); + int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missing_indirect_t *pkt); + int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_direct_t *pkt); +-void rm_unwanted(unsigned logopt, const char *path, int incl, dev_t dev); +-int count_mounts(unsigned logopt, const char *path, dev_t dev); ++void rm_unwanted(struct autofs_point *ap, const char *path, int incl); ++int count_mounts(struct autofs_point *ap, const char *path, dev_t dev); + + #define mounts_mutex_lock(ap) \ + do { \ diff --git a/SOURCES/autofs-5.0.8-check-for-bind-onto-self-in-mount_bind-c.patch b/SOURCES/autofs-5.0.8-check-for-bind-onto-self-in-mount_bind-c.patch new file mode 100644 index 0000000..8f2913b --- /dev/null +++ b/SOURCES/autofs-5.0.8-check-for-bind-onto-self-in-mount_bind-c.patch @@ -0,0 +1,36 @@ +autofs-5.0.8 - check for bind onto self in mount_bind.c + +From: Ian Kent + +Check for an obviously impossible request to bind or symlink to the +same patch for source and target. +--- + CHANGELOG | 1 + + modules/mount_bind.c | 6 ++++++ + 2 files changed, 7 insertions(+) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -85,6 +85,7 @@ + - fix compilation of lookup_ldap.c without sasl. + - fix undefined authtype_requires_creds err if ldap enabled but without sasl. + - pass map_source as function paramter where possible. ++- check for bind onto self in mount_bind.c. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/mount_bind.c ++++ autofs-5.0.7/modules/mount_bind.c +@@ -135,6 +135,12 @@ int mount_mount(struct autofs_point *ap, + if (options == NULL || *options == '\0') + options = "defaults"; + ++ if (!strcmp(what, fullpath)) { ++ debug(ap->logopt, MODPREFIX ++ "cannot mount or symlink %s to itself", fullpath); ++ return 1; ++ } ++ + if (!symlnk && bind_works) { + int status, existed = 1; + diff --git a/SOURCES/autofs-5.0.8-check-for-existing-offset-mount-before-mounting.patch b/SOURCES/autofs-5.0.8-check-for-existing-offset-mount-before-mounting.patch new file mode 100644 index 0000000..8600444 --- /dev/null +++ b/SOURCES/autofs-5.0.8-check-for-existing-offset-mount-before-mounting.patch @@ -0,0 +1,46 @@ +autofs-5.0.8 - check for existing offset mount before mounting + +From: Ian Kent + +The change that introduced the miscellaneous device for autofs +mount control removed a mount point mounted check from the +mount_autofs_offset() function for when the miscellaneous +device is not used. + +But a subsequent change that enabled limited update of the exports +of a hosts mount needed that check. Without it a second occurance +of the offset (corresponding to an export) could be mounted upon +a map re-read. +--- + CHANGELOG | 1 + + daemon/direct.c | 3 +-- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -80,6 +80,7 @@ + - add short host name standard marco variable. + - fix symlink fail message in mount_bind.c. + - add std vars to program map invocation. ++- check for existing offset mount before mounting. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/direct.c ++++ autofs-5.0.7/daemon/direct.c +@@ -671,14 +671,13 @@ int mount_autofs_offset(struct autofs_po + if (!(ret == -1 && errno == ENOENT)) + return MOUNT_OFFSET_FAIL; + } else { +-/* + if (is_mounted(_PROC_MOUNTS, me->key, MNTS_AUTOFS)) { + if (ap->state != ST_READMAP) + warn(ap->logopt, + "trigger %s already mounted", me->key); + return MOUNT_OFFSET_OK; + } +-*/ ++ + if (me->ioctlfd != -1) { + error(ap->logopt, "active offset mount %s", me->key); + return MOUNT_OFFSET_FAIL; diff --git a/SOURCES/autofs-5.0.8-dont-clobber-mapent-for-negative-cache.patch b/SOURCES/autofs-5.0.8-dont-clobber-mapent-for-negative-cache.patch new file mode 100644 index 0000000..b38fdf0 --- /dev/null +++ b/SOURCES/autofs-5.0.8-dont-clobber-mapent-for-negative-cache.patch @@ -0,0 +1,343 @@ +autofs-5.0.8 - dont clobber mapent for negative cache + +From: Ian Kent + +When negative caching a map entry on mount fail don't save the mapent +and restore it when the negative cache timeout expires. + +Deleting the mapent, as is done now, can be expensive especially when +it causes a file read for a large file map. +--- + daemon/lookup.c | 6 ++- + include/automount.h | 9 ++++ + lib/cache.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++- + modules/lookup_file.c | 6 ++- + modules/lookup_hosts.c | 10 +++-- + modules/lookup_ldap.c | 6 ++- + modules/lookup_nisplus.c | 10 +++-- + modules/lookup_program.c | 10 +++-- + modules/lookup_sss.c | 6 ++- + modules/lookup_yp.c | 6 ++- + 10 files changed, 135 insertions(+), 19 deletions(-) + +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -860,7 +860,11 @@ static void update_negative_cache(struct + int rv = CHE_FAIL; + + cache_writelock(map->mc); +- rv = cache_update(map->mc, map, name, NULL, now); ++ me = cache_lookup_distinct(map->mc, name); ++ if (me) ++ rv = cache_push_mapent(me, NULL); ++ else ++ rv = cache_update(map->mc, map, name, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(map->mc, name); + me->status = now + ap->negative_timeout; +--- autofs-5.0.7.orig/include/automount.h ++++ autofs-5.0.7/include/automount.h +@@ -146,6 +146,12 @@ struct mapent_cache { + struct mapent **hash; + }; + ++struct stack { ++ char *mapent; ++ time_t age; ++ struct stack *next; ++}; ++ + struct mapent { + struct mapent *next; + struct list_head ino_index; +@@ -159,6 +165,7 @@ struct mapent { + struct mapent *parent; + char *key; + char *mapent; ++ struct stack *stack; + time_t age; + /* Time of last mount fail */ + time_t status; +@@ -175,6 +182,8 @@ void cache_readlock(struct mapent_cache + void cache_writelock(struct mapent_cache *mc); + int cache_try_writelock(struct mapent_cache *mc); + void cache_unlock(struct mapent_cache *mc); ++int cache_push_mapent(struct mapent *me, char *mapent); ++int cache_pop_mapent(struct mapent *me); + struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map); + struct mapent_cache *cache_init_null_cache(struct master *master); + int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino); +--- autofs-5.0.7.orig/lib/cache.c ++++ autofs-5.0.7/lib/cache.c +@@ -177,6 +177,69 @@ static inline void ino_index_unlock(stru + return; + } + ++/* Save the cache entry mapent field onto a stack and set a new mapent */ ++int cache_push_mapent(struct mapent *me, char *mapent) ++{ ++ struct stack *s; ++ char *new; ++ ++ if (!me->mapent) ++ return CHE_FAIL; ++ ++ if (!mapent) ++ new = NULL; ++ else { ++ new = strdup(mapent); ++ if (!new) ++ return CHE_FAIL; ++ } ++ ++ s = malloc(sizeof(struct stack)); ++ if (!s) { ++ if (new) ++ free(new); ++ return CHE_FAIL; ++ } ++ memset(s, 0, sizeof(*s)); ++ ++ s->mapent = me->mapent; ++ s->age = me->age; ++ me->mapent = mapent; ++ ++ if (me->stack) ++ s->next = me->stack; ++ me->stack = s; ++ ++ return CHE_OK; ++} ++ ++/* Restore cache entry mapent to a previously saved mapent, discard current */ ++int cache_pop_mapent(struct mapent *me) ++{ ++ struct stack *s = me->stack; ++ char *mapent; ++ time_t age; ++ ++ if (!s || !s->mapent) ++ return CHE_FAIL; ++ ++ mapent = s->mapent; ++ age = s->age; ++ me->stack = s->next; ++ free(s); ++ ++ if (age < me->age) { ++ free(mapent); ++ return CHE_OK; ++ } ++ ++ if (me->mapent) ++ free(me->mapent); ++ me->mapent = mapent; ++ ++ return CHE_OK; ++} ++ + struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map) + { + struct mapent_cache *mc; +@@ -578,6 +641,8 @@ int cache_add(struct mapent_cache *mc, s + } else + me->mapent = NULL; + ++ me->stack = NULL; ++ + me->age = age; + me->status = 0; + me->mc = mc; +@@ -689,7 +754,9 @@ void cache_update_negative(struct mapent + int rv = CHE_OK; + + me = cache_lookup_distinct(mc, key); +- if (!me) ++ if (me) ++ rv = cache_push_mapent(me, NULL); ++ else + rv = cache_update(mc, ms, key, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, key); +@@ -858,6 +925,7 @@ int cache_delete(struct mapent_cache *mc + pred = me; + me = me->next; + if (strcmp(this, me->key) == 0) { ++ struct stack *s = me->stack; + if (me->multi && !list_empty(&me->multi_list)) { + ret = CHE_FAIL; + goto done; +@@ -872,6 +940,13 @@ int cache_delete(struct mapent_cache *mc + free(me->key); + if (me->mapent) + free(me->mapent); ++ while (s) { ++ struct stack *next = s->next; ++ if (s->mapent) ++ free(s->mapent); ++ free(s); ++ s = next; ++ } + free(me); + me = pred; + } +@@ -882,6 +957,7 @@ int cache_delete(struct mapent_cache *mc + goto done; + + if (strcmp(this, me->key) == 0) { ++ struct stack *s = me->stack; + if (me->multi && !list_empty(&me->multi_list)) { + ret = CHE_FAIL; + goto done; +@@ -896,6 +972,13 @@ int cache_delete(struct mapent_cache *mc + free(me->key); + if (me->mapent) + free(me->mapent); ++ while (s) { ++ struct stack *next = s->next; ++ if (s->mapent) ++ free(s->mapent); ++ free(s); ++ s = next; ++ } + free(me); + } + done: +--- autofs-5.0.7.orig/modules/lookup_file.c ++++ autofs-5.0.7/modules/lookup_file.c +@@ -988,8 +988,10 @@ int lookup_mount(struct autofs_point *ap + cache_writelock(smc); + sme = cache_lookup_distinct(smc, key); + /* Negative timeout expired for non-existent entry. */ +- if (sme && !sme->mapent) +- cache_delete(smc, key); ++ if (sme && !sme->mapent) { ++ if (cache_pop_mapent(sme) == CHE_FAIL) ++ cache_delete(smc, key); ++ } + cache_unlock(smc); + } + } +--- autofs-5.0.7.orig/modules/lookup_hosts.c ++++ autofs-5.0.7/modules/lookup_hosts.c +@@ -155,7 +155,9 @@ static int do_parse_mount(struct autofs_ + + cache_writelock(mc); + me = cache_lookup_distinct(mc, name); +- if (!me) ++ if (me) ++ rv = cache_push_mapent(me, NULL); ++ else + rv = cache_update(mc, source, name, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, name); +@@ -315,8 +317,10 @@ int lookup_mount(struct autofs_point *ap + cache_writelock(smc); + sme = cache_lookup_distinct(smc, name); + /* Negative timeout expired for non-existent entry. */ +- if (sme && !sme->mapent) +- cache_delete(smc, name); ++ if (sme && !sme->mapent) { ++ if (cache_pop_mapent(sme) == CHE_FAIL) ++ cache_delete(smc, name); ++ } + cache_unlock(smc); + } + } +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -2937,8 +2937,10 @@ int lookup_mount(struct autofs_point *ap + cache_writelock(smc); + sme = cache_lookup_distinct(smc, key); + /* Negative timeout expired for non-existent entry. */ +- if (sme && !sme->mapent) +- cache_delete(smc, key); ++ if (sme && !sme->mapent) { ++ if (cache_pop_mapent(sme) == CHE_FAIL) ++ cache_delete(smc, key); ++ } + cache_unlock(smc); + } + } +--- autofs-5.0.7.orig/modules/lookup_nisplus.c ++++ autofs-5.0.7/modules/lookup_nisplus.c +@@ -509,8 +509,10 @@ int lookup_mount(struct autofs_point *ap + cache_writelock(smc); + sme = cache_lookup_distinct(smc, key); + /* Negative timeout expired for non-existent entry. */ +- if (sme && !sme->mapent) +- cache_delete(smc, key); ++ if (sme && !sme->mapent) { ++ if (cache_pop_mapent(sme) == CHE_FAIL) ++ cache_delete(smc, key); ++ } + cache_unlock(smc); + } + } +@@ -602,7 +604,9 @@ int lookup_mount(struct autofs_point *ap + return NSS_STATUS_TRYAGAIN; + cache_writelock(mc); + me = cache_lookup_distinct(mc, key); +- if (!me) ++ if (me) ++ rv = cache_push_mapent(me, NULL); ++ else + rv = cache_update(mc, source, key, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, key); +--- autofs-5.0.7.orig/modules/lookup_program.c ++++ autofs-5.0.7/modules/lookup_program.c +@@ -156,8 +156,10 @@ int lookup_mount(struct autofs_point *ap + cache_writelock(smc); + sme = cache_lookup_distinct(smc, name); + /* Negative timeout expired for non-existent entry. */ +- if (sme && !sme->mapent) +- cache_delete(smc, name); ++ if (sme && !sme->mapent) { ++ if (cache_pop_mapent(sme) == CHE_FAIL) ++ cache_delete(smc, name); ++ } + cache_unlock(smc); + } + } +@@ -451,7 +453,9 @@ out_free: + + cache_writelock(mc); + me = cache_lookup_distinct(mc, name); +- if (!me) ++ if (me) ++ rv = cache_push_mapent(me, NULL); ++ else + rv = cache_update(mc, source, name, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, name); +--- autofs-5.0.7.orig/modules/lookup_sss.c ++++ autofs-5.0.7/modules/lookup_sss.c +@@ -599,8 +599,10 @@ int lookup_mount(struct autofs_point *ap + cache_writelock(smc); + sme = cache_lookup_distinct(smc, key); + /* Negative timeout expired for non-existent entry. */ +- if (sme && !sme->mapent) +- cache_delete(smc, key); ++ if (sme && !sme->mapent) { ++ if (cache_pop_mapent(sme) == CHE_FAIL) ++ cache_delete(smc, key); ++ } + cache_unlock(smc); + } + } +--- autofs-5.0.7.orig/modules/lookup_yp.c ++++ autofs-5.0.7/modules/lookup_yp.c +@@ -613,8 +613,10 @@ int lookup_mount(struct autofs_point *ap + cache_writelock(smc); + sme = cache_lookup_distinct(smc, key); + /* Negative timeout expired for non-existent entry. */ +- if (sme && !sme->mapent) +- cache_delete(smc, key); ++ if (sme && !sme->mapent) { ++ if (cache_pop_mapent(sme) == CHE_FAIL) ++ cache_delete(smc, key); ++ } + cache_unlock(smc); + } + } diff --git a/SOURCES/autofs-5.0.8-dont-ignore-null-cache-entries-on-multi-mount-umount.patch b/SOURCES/autofs-5.0.8-dont-ignore-null-cache-entries-on-multi-mount-umount.patch new file mode 100644 index 0000000..0a36a2a --- /dev/null +++ b/SOURCES/autofs-5.0.8-dont-ignore-null-cache-entries-on-multi-mount-umount.patch @@ -0,0 +1,47 @@ +autofs-5.0.8 - dont ignore null cache entries on multi mount umount + +From: Ian Kent + +When umounting the offsets of a multi-mount negative cache entries +shouldn't be ignored. Even if the mount they correspond to failed to +mount the trigger still needs to be umounted. + +Not ignoring negative entries when cleaning stale multi-mount entries +isn't obviously the right thing to do but, since the multi-mount entry +should have been refreshed, there shouldn't be any valid negative entries +so they must be stale and need to go. +--- + CHANGELOG | 1 + + lib/mounts.c | 4 ++-- + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -97,6 +97,7 @@ + - fix map source with type lookup. + - fix fix map source with type lookup. + - fix lookup_nss_mount() map lookup. ++- dont ignore null cache entries on multi mount umount. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/mounts.c ++++ autofs-5.0.7/lib/mounts.c +@@ -1804,7 +1804,7 @@ int umount_multi_triggers(struct autofs_ + + oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list); + /* root offset is a special case */ +- if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1) ++ if (!oe || (strlen(oe->key) - start) == 1) + continue; + + /* +@@ -1926,7 +1926,7 @@ int clean_stale_multi_triggers(struct au + + oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list); + /* root offset is a special case */ +- if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1) ++ if (!oe || (strlen(oe->key) - start) == 1) + continue; + + /* Check for and umount stale subtree offsets */ diff --git a/SOURCES/autofs-5.0.8-extend-libldap-serialization.patch b/SOURCES/autofs-5.0.8-extend-libldap-serialization.patch new file mode 100644 index 0000000..52ee891 --- /dev/null +++ b/SOURCES/autofs-5.0.8-extend-libldap-serialization.patch @@ -0,0 +1,71 @@ +autofs-5.0.8 - extend libldap serialization + +From: Leonardo Chiquitto + +It's necessary to serialize calls to ldap_unbind() as well as the +initial bind. +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 20 ++++++++++++++++---- + 2 files changed, 17 insertions(+), 4 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -107,6 +107,7 @@ + - use open(2) instead of access(2) to trigger dependent mounts. + - fix crash due to thread unsafe use of libldap. + - fix deadlock in init_ldap_connection. ++- extend fix for crash due to thread unsafe use of libldap. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -53,8 +53,9 @@ static struct ldap_schema common_schema[ + static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema); + + /* +- * Initialization of LDAP and OpenSSL must be always serialized to +- * avoid corruption of context structures inside these libraries. ++ * Initialization and de-initialization of LDAP and OpenSSL must be ++ * always serialized to avoid corruption of context structures inside ++ * these libraries. + */ + pthread_mutex_t ldapinit_mutex = PTHREAD_MUTEX_INITIALIZER; + +@@ -203,7 +204,7 @@ int bind_ldap_simple(unsigned logopt, LD + return 0; + } + +-int unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) ++int __unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + { + int rv; + +@@ -220,6 +221,17 @@ int unbind_ldap_connection(unsigned logo + return rv; + } + ++int unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) ++{ ++ int rv; ++ ++ ldapinit_mutex_lock(); ++ rv = __unbind_ldap_connection(logopt, ldap, ctxt); ++ ldapinit_mutex_unlock(); ++ ++ return rv; ++} ++ + LDAP *__init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt) + { + LDAP *ldap = NULL; +@@ -280,7 +292,7 @@ LDAP *__init_ldap_connection(unsigned lo + + rv = ldap_start_tls_s(ldap, NULL, NULL); + if (rv != LDAP_SUCCESS) { +- unbind_ldap_connection(logopt, ldap, ctxt); ++ __unbind_ldap_connection(logopt, ldap, ctxt); + if (ctxt->tls_required) { + error(logopt, MODPREFIX + "TLS required but START_TLS failed: %s", diff --git a/SOURCES/autofs-5.0.8-fix-append-options-description-in-README_v5-release.patch b/SOURCES/autofs-5.0.8-fix-append-options-description-in-README_v5-release.patch new file mode 100644 index 0000000..5f40a4d --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-append-options-description-in-README_v5-release.patch @@ -0,0 +1,37 @@ +autofs-5.0.8 - fix incorrect append options description in README.v5-release + +From: Ian Kent + +The statement about options not being appended by default isn't correct +any more. +--- + CHANGELOG | 1 + + README.v5.release | 7 ++++--- + 2 files changed, 5 insertions(+), 3 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -102,6 +102,7 @@ + - simple coverity fixes. + - fixes for samples/auto.master. + - fix variable substitution description. ++- fix incorrect append options description in README.v5-release. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/README.v5.release ++++ autofs-5.0.7/README.v5.release +@@ -27,9 +27,10 @@ Differences between version 4 and versio + - `autofs' version 5.0.0 will refuse to run if it cannot find an + autofs4 kernel module that supports protocol version 5.00 or above. + +-- mount options present in the master map are now overridden by mount +- options in map entries instead of being accumulated. This behaviour +- is in line with other industry automount implementations. ++- mount options present in the master map are accumulated by default ++ which is different to the behavior of some other autofs ++ implementations. A configuration option is available to change this ++ behavior if required. + + New in 5.0.0 is: + diff --git a/SOURCES/autofs-5.0.8-fix-cache-readlock-not-taken-on-lookup.patch b/SOURCES/autofs-5.0.8-fix-cache-readlock-not-taken-on-lookup.patch new file mode 100644 index 0000000..d38258d --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-cache-readlock-not-taken-on-lookup.patch @@ -0,0 +1,38 @@ +autofs-5.0.8 - fix cache readlock not taken on lookup + +From: Ian Kent + +In modules/lookup_yp.c:check_map_indirect() there's a missing cache +readlock. +--- + CHANGELOG | 1 + + modules/lookup_yp.c | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -81,6 +81,7 @@ + - fix symlink fail message in mount_bind.c. + - add std vars to program map invocation. + - check for existing offset mount before mounting. ++- fix cache readlock not taken on lookup. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_yp.c ++++ autofs-5.0.7/modules/lookup_yp.c +@@ -517,9 +517,13 @@ static int check_map_indirect(struct aut + * If the server is down and the entry exists in the cache + * and belongs to this map return success and use the entry. + */ ++ cache_readlock(mc); + exists = cache_lookup(mc, key); +- if (exists && exists->source == source) ++ if (exists && exists->source == source) { ++ cache_unlock(mc); + return NSS_STATUS_SUCCESS; ++ } ++ cache_unlock(mc); + + warn(ap->logopt, + MODPREFIX "lookup for %s failed: %s", diff --git a/SOURCES/autofs-5.0.8-fix-deadlock-in-init-ldap-connection.patch b/SOURCES/autofs-5.0.8-fix-deadlock-in-init-ldap-connection.patch new file mode 100644 index 0000000..835768d --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-deadlock-in-init-ldap-connection.patch @@ -0,0 +1,35 @@ +Fix deadlock in init_ldap_connection() + +From: Leonardo Chiquitto + +Commit 9fc20db13 ("fix crash due to thread unsafe use of libldap") +introduced a deadlock in init_ldap_connection(). When TLS is on, +this function will call itself recursively and try to lock a mutex +that's already owned by the thread. Fix the problem by using the +lockless version. +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -106,6 +106,7 @@ + - fix mistake in assignment. + - use open(2) instead of access(2) to trigger dependent mounts. + - fix crash due to thread unsafe use of libldap. ++- fix deadlock in init_ldap_connection. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -288,7 +288,7 @@ LDAP *__init_ldap_connection(unsigned lo + return NULL; + } + ctxt->use_tls = LDAP_TLS_DONT_USE; +- ldap = init_ldap_connection(logopt, uri, ctxt); ++ ldap = __init_ldap_connection(logopt, uri, ctxt); + if (ldap) + ctxt->use_tls = LDAP_TLS_INIT; + return ldap; diff --git a/SOURCES/autofs-5.0.8-fix-external-env-configure.patch b/SOURCES/autofs-5.0.8-fix-external-env-configure.patch new file mode 100644 index 0000000..0d77d21 --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-external-env-configure.patch @@ -0,0 +1,45 @@ +autofs-5.0.8 - fix external env configure + +From: Ian Kent + +Macro lookup can also resolve names in the external environment. +The configure script disables this by default but the configure +help implies it is enabled by default. +--- + CHANGELOG | 1 + + configure | 2 +- + configure.in | 2 +- + 3 files changed, 3 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -92,6 +92,7 @@ + - fix macro_addvar() and move init to main thread. + - change walk_tree() to take ap. + - add negative cache lookup to hesiod lookup. ++- fix external env configure. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/configure ++++ autofs-5.0.7/configure +@@ -5608,7 +5608,7 @@ else + enableval=yes + fi + +-if test x$enable_ext_env = xyes; then ++if test x$enable_ext_env = xyes -o x$enableval = xyes; then + + $as_echo "#define ENABLE_EXT_ENV 1" >>confdefs.h + +--- autofs-5.0.7.orig/configure.in ++++ autofs-5.0.7/configure.in +@@ -346,7 +346,7 @@ AC_SUBST(DAEMON_LDFLAGS) + AC_ARG_ENABLE(ext-env, + [ --disable-ext-env disable search in environment for substitution variable],, + enableval=yes) +-if test x$enable_ext_env = xyes; then ++if test x$enable_ext_env = xyes -o x$enableval = xyes; then + AC_DEFINE(ENABLE_EXT_ENV, 1, [leave this alone]) + fi + diff --git a/SOURCES/autofs-5.0.8-fix-fix-map-source-with-type-lookup.patch b/SOURCES/autofs-5.0.8-fix-fix-map-source-with-type-lookup.patch new file mode 100644 index 0000000..bf80577 --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-fix-map-source-with-type-lookup.patch @@ -0,0 +1,51 @@ +autofs-5.0.8 - fix fix map source with type lookup + +From: Ian Kent + +The recent change to make autofs look in the defined map directory +for map source file (or nss source files) when the map doesn't start +with a "/" broke the internal hosts map (thanks for alerting me to +this Leonardo). +--- + CHANGELOG | 1 + + daemon/lookup.c | 10 ++++++++-- + 2 files changed, 9 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -95,6 +95,7 @@ + - fix external env configure. + - make autofs(5) consistent with auto.master(5). + - fix map source with type lookup. ++- fix fix map source with type lookup. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -418,8 +418,11 @@ static int lookup_map_read_map(struct au + { + char *path; + +- if (!map->argv[0]) ++ if (!map->argv[0]) { ++ if (!strcmp(map->type, "hosts")) ++ return do_read_map(ap, map, age); + return NSS_STATUS_UNKNOWN; ++ } + + /* + * This is only called when map->type != NULL. +@@ -817,8 +820,11 @@ static int do_name_lookup_mount(struct a + { + char *path; + +- if (!map->argv[0]) ++ if (!map->argv[0]) { ++ if (!strcmp(map->type, "hosts")) ++ return do_lookup_mount(ap, map, name, name_len); + return NSS_STATUS_UNKNOWN; ++ } + + /* + * This is only called when map->type != NULL. diff --git a/SOURCES/autofs-5.0.8-fix-fix-options-compare.patch b/SOURCES/autofs-5.0.8-fix-fix-options-compare.patch new file mode 100644 index 0000000..1c7c1ba --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-fix-options-compare.patch @@ -0,0 +1,37 @@ +autofs-5.0.8 - fix fix options compare + +From: Ian Kent + +The change to fix the mount options compare replaced the strncmp() +function used to compare substrings of options with an internal +function that also used the passed in length for the compare. + +But the case of a passed in length of 0 was not handled and for +that case the function returned a value different to strncmp() +and code that relied on that behaviour n longer behaves as expected. +--- + CHANGELOG | 1 + + lib/cat_path.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -74,6 +74,7 @@ + - fix fix negative status being reset on map read. + - check for non existent negative entries in lookup_ghost(). + - fix options compare. ++- fix fix options compare. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/cat_path.c ++++ autofs-5.0.7/lib/cat_path.c +@@ -92,7 +92,7 @@ int _strncmp(const char *s1, const char + { + size_t len = strlen(s1); + +- if (n != len) ++ if (n && n != len) + return n - len; + return strncmp(s1, s2, n); + } diff --git a/SOURCES/autofs-5.0.8-fix-inconsistent-error-returns-in-handle_packet_missing_direct.patch b/SOURCES/autofs-5.0.8-fix-inconsistent-error-returns-in-handle_packet_missing_direct.patch new file mode 100644 index 0000000..cc5cab4 --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-inconsistent-error-returns-in-handle_packet_missing_direct.patch @@ -0,0 +1,68 @@ +autofs-5.0.8 - fix inconsistent error returns in handle_packet_missing_direct() + +From: Ian Kent + +How to handle mount requests that arrive during a shutdown is a big +problem. + +Currently common cases result in the requesting process being sent a +fail status and success being returned to the calling autofs process. + +There are a number of places where a fail is returned to the calling +process (such as memeory allocation errors) which should cause the +daemon to exit. But when a request arrives during a shutdown the +daemon is usually not ready to shutdown and instead performs recovery +and returns to a ready state instead of shutting down. + +There were a few places in handle_packet_missing_direct() where a fail +was being returned when a success should have been returned which was +preventing the completion of the shutdown. + +This is not ideal because during a restart of the daemon processes +requesting a mount could receive a mount failure. But this has been +the policy for while now and it's very difficult to do in a different +way. +--- + CHANGELOG | 1 + + daemon/direct.c | 6 +++--- + 2 files changed, 4 insertions(+), 3 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -98,6 +98,7 @@ + - fix fix map source with type lookup. + - fix lookup_nss_mount() map lookup. + - dont ignore null cache entries on multi mount umount. ++- fix inconsistent error returns in handle_packet_missing_direct(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/direct.c ++++ autofs-5.0.7/daemon/direct.c +@@ -1384,7 +1384,7 @@ int handle_packet_missing_direct(struct + master_source_unlock(ap->entry); + master_mutex_unlock(); + pthread_setcancelstate(state, NULL); +- return 1; ++ return 0; + } + + /* Check if we recorded a mount fail for this key */ +@@ -1409,7 +1409,7 @@ int handle_packet_missing_direct(struct + master_source_unlock(ap->entry); + master_mutex_unlock(); + pthread_setcancelstate(state, NULL); +- return 1; ++ return 0; + } + + mt = malloc(sizeof(struct pending_args)); +@@ -1423,7 +1423,7 @@ int handle_packet_missing_direct(struct + master_source_unlock(ap->entry); + master_mutex_unlock(); + pthread_setcancelstate(state, NULL); +- return 1; ++ return 0; + } + memset(mt, 0, sizeof(struct pending_args)); + diff --git a/SOURCES/autofs-5.0.8-fix-lookup_nss_mount-map-lookup.patch b/SOURCES/autofs-5.0.8-fix-lookup_nss_mount-map-lookup.patch new file mode 100644 index 0000000..c4e7d6d --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-lookup_nss_mount-map-lookup.patch @@ -0,0 +1,38 @@ +autofs-5.0.8 - fix lookup_nss_mount() map lookup + +From: Ian Kent + +A mount that may have multiple maps (direct mounts) should try each +source and if nsswicth is used then each instance should be tried +before moving to the next map. + +Moving to the next map if an nss instance is not found makes no sense. +--- + CHANGELOG | 1 + + daemon/lookup.c | 4 +--- + 2 files changed, 2 insertions(+), 3 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -96,6 +96,7 @@ + - make autofs(5) consistent with auto.master(5). + - fix map source with type lookup. + - fix fix map source with type lookup. ++- fix lookup_nss_mount() map lookup. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -1045,10 +1045,8 @@ int lookup_nss_mount(struct autofs_point + + result = lookup_map_name(this, ap, map, name, name_len); + +- if (result == NSS_STATUS_UNKNOWN) { +- map = map->next; ++ if (result == NSS_STATUS_UNKNOWN) + continue; +- } + + status = check_nss_result(this, result); + if (status >= 0) { diff --git a/SOURCES/autofs-5.0.8-fix-macro_addvar-and-move-init-to-main-thread.patch b/SOURCES/autofs-5.0.8-fix-macro_addvar-and-move-init-to-main-thread.patch new file mode 100644 index 0000000..5fa3e4c --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-macro_addvar-and-move-init-to-main-thread.patch @@ -0,0 +1,242 @@ +autofs-5.0.8 - fix macro_addvar() and move init to main thread + +From: Ian Kent + +- move macro table initialization to the main thread. +- change to using malloc() instead of realloc() in macro_global_addvar() + and macro_addvar(). +- fix possible incorrect return from macro_addvar(). +--- + CHANGELOG | 1 + + daemon/automount.c | 16 ++++++++++++++++ + lib/macros.c | 25 ++++++++++++++++++++----- + modules/parse_sun.c | 9 --------- + 4 files changed, 37 insertions(+), 14 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -89,6 +89,7 @@ + - fix symlink expire. + - fix master map type check. + - fix bad mkdir permission on create. ++- fix macro_addvar() and move init to main thread. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/automount.c ++++ autofs-5.0.7/daemon/automount.c +@@ -2129,6 +2129,9 @@ int main(int argc, char *argv[]) + program); + #endif + ++ /* Get processor information for predefined escapes */ ++ macro_init(); ++ + if (dumpmaps) { + struct master_mapent *entry; + struct list_head *head, *p; +@@ -2152,6 +2155,7 @@ int main(int argc, char *argv[]) + master_list = master_new(master, timeout, ghost); + if (!master_list) { + printf("%s: can't create master map", program); ++ macro_free_global_table(); + exit(1); + } + +@@ -2163,6 +2167,7 @@ int main(int argc, char *argv[]) + if (!nc) { + printf("%s: failed to init null map cache for %s", + program, master_list->name); ++ macro_free_global_table(); + exit(1); + } + master_list->nc = nc; +@@ -2187,6 +2192,7 @@ int main(int argc, char *argv[]) + master_free_mapent(entry); + } + master_kill(master_list); ++ macro_free_global_table(); + + exit(0); + } +@@ -2198,6 +2204,7 @@ int main(int argc, char *argv[]) + + if (!master_list) { + printf("%s: can't create master map %s", program, argv[0]); ++ macro_free_global_table(); + exit(1); + } + +@@ -2209,6 +2216,7 @@ int main(int argc, char *argv[]) + res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); + close(start_pipefd[1]); + release_flag_file(); ++ macro_free_global_table(); + exit(1); + } + +@@ -2218,6 +2226,7 @@ int main(int argc, char *argv[]) + res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); + close(start_pipefd[1]); + release_flag_file(); ++ macro_free_global_table(); + exit(1); + } + +@@ -2228,6 +2237,7 @@ int main(int argc, char *argv[]) + res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); + close(start_pipefd[1]); + release_flag_file(); ++ macro_free_global_table(); + exit(1); + } + +@@ -2239,6 +2249,7 @@ int main(int argc, char *argv[]) + res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); + close(start_pipefd[1]); + release_flag_file(); ++ macro_free_global_table(); + exit(1); + } + #endif +@@ -2257,6 +2268,7 @@ int main(int argc, char *argv[]) + res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); + close(start_pipefd[1]); + release_flag_file(); ++ macro_free_global_table(); + exit(1); + } + +@@ -2268,6 +2280,7 @@ int main(int argc, char *argv[]) + res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); + close(start_pipefd[1]); + release_flag_file(); ++ macro_free_global_table(); + exit(1); + } + +@@ -2277,6 +2290,7 @@ int main(int argc, char *argv[]) + res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); + close(start_pipefd[1]); + release_flag_file(); ++ macro_free_global_table(); + exit(1); + } + +@@ -2299,6 +2313,7 @@ int main(int argc, char *argv[]) + res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); + close(start_pipefd[1]); + release_flag_file(); ++ macro_free_global_table(); + exit(3); + } + +@@ -2323,6 +2338,7 @@ int main(int argc, char *argv[]) + } + closelog(); + release_flag_file(); ++ macro_free_global_table(); + + #ifdef TIRPC_WORKAROUND + if (dh_tirpc) +--- autofs-5.0.7.orig/lib/macros.c ++++ autofs-5.0.7/lib/macros.c +@@ -35,6 +35,7 @@ static struct substvar + }; + + static struct substvar *system_table = &sv_osvers; ++static unsigned int macro_init_done = 0; + + static pthread_mutex_t table_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_mutex_t macro_mutex = PTHREAD_MUTEX_INITIALIZER; +@@ -62,6 +63,12 @@ void dump_table(struct substvar *table) + /* Get processor information for predefined macro definitions */ + void macro_init(void) + { ++ macro_lock(); ++ if (macro_init_done) { ++ macro_unlock(); ++ return; ++ } ++ + uname(&un); + /* + * uname -p is not defined on Linux. Make it the same as +@@ -71,6 +78,10 @@ void macro_init(void) + if (processor[0] == 'i' && processor[1] >= '3' && + !strcmp(processor + 2, "86")) + processor[1] = '3'; ++ ++ macro_init_done = 1; ++ macro_unlock(); ++ return; + } + + int macro_is_systemvar(const char *str, int len) +@@ -118,10 +129,11 @@ int macro_global_addvar(const char *str, + } + + if (sv && !sv->readonly) { +- char *this = realloc(sv->val, strlen(value) + 1); ++ char *this = malloc(strlen(value) + 1); + if (!this) + goto done; +- strcat(this, value); ++ strcpy(this, value); ++ free(sv->val); + sv->val = this; + ret = 1; + } else { +@@ -213,13 +225,16 @@ macro_addvar(struct substvar *table, con + } + + if (lv) { +- char *this = realloc(lv->val, strlen(value) + 1); ++ char *this = malloc(strlen(value) + 1); + if (!this) { + lv = table; + goto done; + } +- strcat(this, value); ++ strcpy(this, value); ++ free(lv->val); + lv->val = this; ++ if (lv != table) ++ lv = table; + } else { + struct substvar *new; + char *def, *val; +@@ -413,7 +428,7 @@ macro_findvar(const struct substvar *tab + etmp[len]='\0'; + + if ((value=getenv(etmp)) != NULL) { +- lv_var = macro_addvar(table, str, len, value); ++ lv_var = macro_addvar((struct substvar *) table, str, len, value); + return(lv_var); + } + #endif +--- autofs-5.0.7.orig/modules/parse_sun.c ++++ autofs-5.0.7/modules/parse_sun.c +@@ -41,7 +41,6 @@ int parse_version = AUTOFS_PARSE_VERSION + + static struct mount_mod *mount_nfs = NULL; + static int init_ctr = 0; +-static int macro_init_done = 0; + static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER; + + static void instance_mutex_lock(void) +@@ -243,14 +242,6 @@ int parse_init(int argc, const char *con + int i, bval; + unsigned int append_options; + +- /* Get processor information for predefined escapes */ +- macro_lock(); +- if (!macro_init_done) { +- macro_init_done = 1; +- macro_init(); +- } +- macro_unlock(); +- + /* Set up context and escape chain */ + + if (!(ctxt = (struct parse_context *) malloc(sizeof(struct parse_context)))) { diff --git a/SOURCES/autofs-5.0.8-fix-map-source-with-type-lookup.patch b/SOURCES/autofs-5.0.8-fix-map-source-with-type-lookup.patch new file mode 100644 index 0000000..6713551 --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-map-source-with-type-lookup.patch @@ -0,0 +1,192 @@ +autofs-5.0.8 - fix map source with type lookup + +From: Ian Kent + +If the map source type is specified the map name must be a full +path. + +But we should be able to give a plain map name and expect autofs +to look in the compiled in maps directory. +--- + CHANGELOG | 1 + daemon/lookup.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 99 insertions(+), 13 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -94,6 +94,7 @@ + - add negative cache lookup to hesiod lookup. + - fix external env configure. + - make autofs(5) consistent with auto.master(5). ++- fix map source with type lookup. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -100,6 +100,27 @@ static int do_read_master(struct master + return status; + } + ++static char *find_map_path(struct map_source *map) ++{ ++ struct stat st; ++ char *path; ++ ++ path = malloc(strlen(AUTOFS_MAP_DIR) + strlen(map->argv[0]) + 2); ++ if (!path) ++ return NULL; ++ ++ strcpy(path, AUTOFS_MAP_DIR); ++ strcat(path, "/"); ++ strcat(path, map->argv[0]); ++ ++ if (!stat(path, &st)) ++ return path; ++ ++ free(path); ++ ++ return NULL; ++} ++ + static int read_master_map(struct master *master, char *type, time_t age) + { + unsigned int logopt = master->logopt; +@@ -392,6 +413,42 @@ static void argv_cleanup(void *arg) + return; + } + ++static int lookup_map_read_map(struct autofs_point *ap, ++ struct map_source *map, time_t age) ++{ ++ char *path; ++ ++ if (!map->argv[0]) ++ return NSS_STATUS_UNKNOWN; ++ ++ /* ++ * This is only called when map->type != NULL. ++ * We only need to look for a map if source type is ++ * file and the map name doesn't begin with a "/". ++ */ ++ if (strncmp(map->type, "file", 4)) ++ return do_read_map(ap, map, age); ++ ++ if (map->argv[0][0] == '/') ++ return do_read_map(ap, map, age); ++ ++ path = find_map_path(map); ++ if (!path) ++ return NSS_STATUS_UNKNOWN; ++ ++ if (map->argc >= 1) { ++ if (map->argv[0]) ++ free((char *) map->argv[0]); ++ map->argv[0] = path; ++ } else { ++ error(ap->logopt, "invalid arguments for autofs_point"); ++ free(path); ++ return NSS_STATUS_UNKNOWN; ++ } ++ ++ return do_read_map(ap, map, age); ++} ++ + static enum nsswitch_status read_map_source(struct nss_source *this, + struct autofs_point *ap, struct map_source *map, time_t age) + { +@@ -428,14 +485,10 @@ static enum nsswitch_status read_map_sou + tmap.argc = 0; + tmap.argv = NULL; + +- path = malloc(strlen(AUTOFS_MAP_DIR) + strlen(map->argv[0]) + 2); ++ path = find_map_path(map); + if (!path) + return NSS_STATUS_UNKNOWN; + +- strcpy(path, AUTOFS_MAP_DIR); +- strcat(path, "/"); +- strcat(path, map->argv[0]); +- + if (map->argc >= 1) { + tmap.argc = map->argc; + tmap.argv = copy_argv(map->argc, map->argv); +@@ -496,7 +549,7 @@ int lookup_nss_read_map(struct autofs_po + debug(ap->logopt, + "reading map %s %s", + map->type, map->argv[0]); +- result = do_read_map(ap, map, age); ++ result = lookup_map_read_map(ap, map, age); + map = map->next; + continue; + } +@@ -758,6 +811,43 @@ static int lookup_name_source_instance(s + return do_lookup_mount(ap, instance, name, name_len); + } + ++static int do_name_lookup_mount(struct autofs_point *ap, ++ struct map_source *map, ++ const char *name, int name_len) ++{ ++ char *path; ++ ++ if (!map->argv[0]) ++ return NSS_STATUS_UNKNOWN; ++ ++ /* ++ * This is only called when map->type != NULL. ++ * We only need to look for a map if source type is ++ * file and the map name doesn't begin with a "/". ++ */ ++ if (strncmp(map->type, "file", 4)) ++ return do_lookup_mount(ap, map, name, name_len); ++ ++ if (map->argv[0][0] == '/') ++ return do_lookup_mount(ap, map, name, name_len); ++ ++ path = find_map_path(map); ++ if (!path) ++ return NSS_STATUS_UNKNOWN; ++ ++ if (map->argc >= 1) { ++ if (map->argv[0]) ++ free((char *) map->argv[0]); ++ map->argv[0] = path; ++ } else { ++ error(ap->logopt, "invalid arguments for autofs_point"); ++ free(path); ++ return NSS_STATUS_UNKNOWN; ++ } ++ ++ return do_lookup_mount(ap, map, name, name_len); ++} ++ + static enum nsswitch_status lookup_map_name(struct nss_source *this, + struct autofs_point *ap, struct map_source *map, + const char *name, int name_len) +@@ -793,14 +883,10 @@ static enum nsswitch_status lookup_map_n + tmap.argc = 0; + tmap.argv = NULL; + +- path = malloc(strlen(AUTOFS_MAP_DIR) + strlen(map->argv[0]) + 2); ++ path = find_map_path(map); + if (!path) + return NSS_STATUS_UNKNOWN; + +- strcpy(path, AUTOFS_MAP_DIR); +- strcat(path, "/"); +- strcat(path, map->argv[0]); +- + if (map->argc >= 1) { + tmap.argc = map->argc; + tmap.argv = copy_argv(map->argc, map->argv); +@@ -909,8 +995,7 @@ int lookup_nss_mount(struct autofs_point + sched_yield(); + + if (map->type) { +- result = do_lookup_mount(ap, map, name, name_len); +- ++ result = do_name_lookup_mount(ap, map, name, name_len); + if (result == NSS_STATUS_SUCCESS) + break; + diff --git a/SOURCES/autofs-5.0.8-fix-master-map-type-check.patch b/SOURCES/autofs-5.0.8-fix-master-map-type-check.patch new file mode 100644 index 0000000..77a9e4b --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-master-map-type-check.patch @@ -0,0 +1,54 @@ +autofs-5.0.8 - fix master map type check + +From: Ian Kent + +Map type has format [,] but the master map type check +for old style map syntax doesn't allow for . +--- + CHANGELOG | 1 + + daemon/lookup.c | 24 ++++++++++++++++-------- + 2 files changed, 17 insertions(+), 8 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -87,6 +87,7 @@ + - pass map_source as function paramter where possible. + - check for bind onto self in mount_bind.c. + - fix symlink expire. ++- fix master map type check. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -171,14 +171,22 @@ int lookup_nss_read_master(struct master + char source[10]; + + memset(source, 0, 10); +- if (!strncmp(name, "file:", 5) || +- !strncmp(name, "yp:", 3) || +- !strncmp(name, "nis:", 4) || +- !strncmp(name, "nisplus:", 8) || +- !strncmp(name, "ldap:", 5) || +- !strncmp(name, "ldaps:", 6) || +- !strncmp(name, "sss:", 4) || +- !strncmp(name, "dir:", 4)) { ++ if ((!strncmp(name, "file", 4) && ++ (name[4] == ',' || name[4] == ':')) || ++ (!strncmp(name, "yp", 3) && ++ (name[3] == ',' || name[3] == ':')) || ++ (!strncmp(name, "nis", 3) && ++ (name[3] == ',' || name[3] == ':')) || ++ (!strncmp(name, "nisplus", 7) && ++ (name[7] == ',' || name[7] == ':')) || ++ (!strncmp(name, "ldap", 4) && ++ (name[4] == ',' || name[4] == ':')) || ++ (!strncmp(name, "ldaps", 5) && ++ (name[5] == ',' || name[5] == ':')) || ++ (!strncmp(name, "sss", 3) || ++ (name[3] == ',' || name[3] == ':')) || ++ (!strncmp(name, "dir", 3) && ++ (name[3] == ',' || name[3] == ':'))) { + strncpy(source, name, tmp - name); + + /* diff --git a/SOURCES/autofs-5.0.8-fix-max-declaration.patch b/SOURCES/autofs-5.0.8-fix-max-declaration.patch new file mode 100644 index 0000000..6b9f41e --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-max-declaration.patch @@ -0,0 +1,42 @@ +autofs-5.0.8 - fix max() declaration + +From: Ian Kent + +Use a name other than the already defined max(). +--- + CHANGELOG | 1 + + modules/replicated.c | 6 +++--- + 2 files changed, 4 insertions(+), 3 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -75,6 +75,7 @@ + - check for non existent negative entries in lookup_ghost(). + - fix options compare. + - fix fix options compare. ++- fix max() declaration. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/replicated.c ++++ autofs-5.0.7/modules/replicated.c +@@ -73,8 +73,8 @@ static int volatile ifc_last_len = 0; + /* Get numeric value of the n bits starting at position p */ + #define getbits(x, p, n) ((x >> (p + 1 - n)) & ~(~0 << n)) + +-#define max(x, y) (x >= y ? x : y) +-#define mmax(x, y, z) (max(x, y) == x ? max(x, z) : max(y, z)) ++#define mymax(x, y) (x >= y ? x : y) ++#define mmax(x, y, z) (mymax(x, y) == x ? mymax(x, z) : mymax(y, z)) + + unsigned int ipv6_mask_cmp(uint32_t *host, uint32_t *iface, uint32_t *mask) + { +@@ -961,7 +961,7 @@ int prune_host_list(unsigned logopt, str + + max_tcp_count = mmax(v4_tcp_count, v3_tcp_count, v2_tcp_count); + max_udp_count = mmax(v4_udp_count, v3_udp_count, v2_udp_count); +- max_count = max(max_tcp_count, max_udp_count); ++ max_count = mymax(max_tcp_count, max_udp_count); + + if (max_count == v4_tcp_count) { + selected_version = NFS4_TCP_SUPPORTED; diff --git a/SOURCES/autofs-5.0.8-fix-negative-status-being-reset-on-map-read.patch b/SOURCES/autofs-5.0.8-fix-negative-status-being-reset-on-map-read.patch new file mode 100644 index 0000000..99ca48f --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-negative-status-being-reset-on-map-read.patch @@ -0,0 +1,41 @@ +autofs-5.0.8 - fix negative status being reset on map read + +From: Ian Kent + +The map entry status field, which holds the negative cache timeout, +gets reset on a map re-read. + +If the negative map entry was added at the same time as the map +read and it was for an entry that was never in the map, the +status gets reset even though the entry is still a valid +negative entry. + +Consequently lookups for non-existent map entries are never +seen as negative and the lookup always continues. +--- + CHANGELOG | 1 + + daemon/lookup.c | 3 ++- + 2 files changed, 3 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -70,6 +70,7 @@ + - get_nfs_info() should query portmapper if port is not given. + - fix rpc_portmap_getport() proto not set. + - fix protmap not trying proto v2. ++- fix negative status being reset on map read. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -1042,7 +1042,8 @@ void lookup_prune_one_cache(struct autof + * Reset time of last fail for valid map entries to + * force entry update and subsequent mount retry. + */ +- me->status = 0; ++ if (me->mapent) ++ me->status = 0; + me = cache_enumerate(mc, me); + continue; + } diff --git a/SOURCES/autofs-5.0.8-fix-options-compare.patch b/SOURCES/autofs-5.0.8-fix-options-compare.patch new file mode 100644 index 0000000..5c6b127 --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-options-compare.patch @@ -0,0 +1,212 @@ +autofs-5.0.8 - fix options compare + +From: Ian Kent + +When checking for options in mount locations incorrect matches +can occur when the length of the option string is not also used +for the check. +--- + CHANGELOG | 1 + + include/automount.h | 1 + + lib/cat_path.c | 9 +++++++++ + modules/mount_autofs.c | 12 ++++++------ + modules/mount_bind.c | 2 +- + modules/mount_ext2.c | 2 +- + modules/mount_nfs.c | 34 +++++++++++++++++----------------- + modules/parse_sun.c | 20 ++++++++++---------- + 8 files changed, 46 insertions(+), 35 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -73,6 +73,7 @@ + - fix negative status being reset on map read. + - fix fix negative status being reset on map read. + - check for non existent negative entries in lookup_ghost(). ++- fix options compare. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/include/automount.h ++++ autofs-5.0.7/include/automount.h +@@ -335,6 +335,7 @@ size_t _strlen(const char *str, size_t m + int cat_path(char *buf, size_t len, const char *dir, const char *base); + int ncat_path(char *buf, size_t len, + const char *dir, const char *base, size_t blen); ++int _strncmp(const char *s1, const char *s2, size_t n); + + /* Core automount definitions */ + +--- autofs-5.0.7.orig/lib/cat_path.c ++++ autofs-5.0.7/lib/cat_path.c +@@ -87,3 +87,12 @@ int ncat_path(char *buf, size_t len, + return cat_path(buf, len, dir, name); + } + ++/* Compare first n bytes of s1 and s2 and that n == strlen(s1) */ ++int _strncmp(const char *s1, const char *s2, size_t n) ++{ ++ size_t len = strlen(s1); ++ ++ if (n != len) ++ return n - len; ++ return strncmp(s1, s2, n); ++} +--- autofs-5.0.7.orig/modules/mount_autofs.c ++++ autofs-5.0.7/modules/mount_autofs.c +@@ -116,17 +116,17 @@ int mount_mount(struct autofs_point *ap, + while (*comma != '\0' && *comma != ',') + comma++; + +- if (strncmp(cp, "nobrowse", 8) == 0) ++ if (_strncmp(cp, "nobrowse", 8) == 0) + ghost = 0; +- else if (strncmp(cp, "nobind", 6) == 0) ++ else if (_strncmp(cp, "nobind", 6) == 0) + nobind = 1; +- else if (strncmp(cp, "browse", 6) == 0) ++ else if (_strncmp(cp, "browse", 6) == 0) + ghost = 1; +- else if (strncmp(cp, "symlink", 7) == 0) ++ else if (_strncmp(cp, "symlink", 7) == 0) + symlnk = 1; +- else if (strncmp(cp, "hosts", 5) == 0) ++ else if (_strncmp(cp, "hosts", 5) == 0) + hosts = 1; +- else if (strncmp(cp, "timeout=", 8) == 0) { ++ else if (_strncmp(cp, "timeout=", 8) == 0) { + char *val = strchr(cp, '='); + unsigned tout; + if (val) { +--- autofs-5.0.7.orig/modules/mount_bind.c ++++ autofs-5.0.7/modules/mount_bind.c +@@ -107,7 +107,7 @@ int mount_mount(struct autofs_point *ap, + end--; + + o_len = end - cp + 1; +- if (strncmp("symlink", cp, o_len) == 0) ++ if (_strncmp("symlink", cp, o_len) == 0) + symlnk = 1; + } + } +--- autofs-5.0.7.orig/modules/mount_ext2.c ++++ autofs-5.0.7/modules/mount_ext2.c +@@ -77,7 +77,7 @@ int mount_mount(struct autofs_point *ap, + + if (options && options[0]) { + for (p = options; (p1 = strchr(p, ',')); p = p1) +- if (!strncmp(p, "ro", p1 - p) && ++p1 - p == sizeof("ro")) ++ if (!_strncmp(p, "ro", p1 - p) && ++p1 - p == sizeof("ro")) + ro = 1; + if (!strcmp(p, "ro")) + ro = 1; +--- autofs-5.0.7.orig/modules/mount_nfs.c ++++ autofs-5.0.7/modules/mount_nfs.c +@@ -126,32 +126,32 @@ int mount_mount(struct autofs_point *ap, + + o_len = end - cp + 1; + +- if (strncmp("proto=rdma", cp, o_len) == 0 || +- strncmp("rdma", cp, o_len) == 0) ++ if (_strncmp("proto=rdma", cp, o_len) == 0 || ++ _strncmp("rdma", cp, o_len) == 0) + rdma = 1; + +- if (strncmp("nosymlink", cp, o_len) == 0) { ++ if (_strncmp("nosymlink", cp, o_len) == 0) { + warn(ap->logopt, MODPREFIX + "the \"nosymlink\" option is depricated " + "and will soon be removed, " + "use the \"nobind\" option instead"); + nosymlink = 1; +- } else if (strncmp("nobind", cp, o_len) == 0) { ++ } else if (_strncmp("nobind", cp, o_len) == 0) { + nobind = 1; +- } else if (strncmp("no-use-weight-only", cp, o_len) == 0) { ++ } else if (_strncmp("no-use-weight-only", cp, o_len) == 0) { + flags &= ~MOUNT_FLAG_USE_WEIGHT_ONLY; +- } else if (strncmp("use-weight-only", cp, o_len) == 0) { ++ } else if (_strncmp("use-weight-only", cp, o_len) == 0) { + flags |= MOUNT_FLAG_USE_WEIGHT_ONLY; + } else { +- if (strncmp("vers=4", cp, o_len) == 0 || +- strncmp("nfsvers=4", cp, o_len) == 0) ++ if (_strncmp("vers=4", cp, o_len) == 0 || ++ _strncmp("nfsvers=4", cp, o_len) == 0) + vers = NFS4_VERS_MASK | TCP_SUPPORTED; +- else if (strncmp("vers=3", cp, o_len) == 0 || +- strncmp("nfsvers=3", cp, o_len) == 0) { ++ else if (_strncmp("vers=3", cp, o_len) == 0 || ++ _strncmp("nfsvers=3", cp, o_len) == 0) { + vers &= ~(NFS4_VERS_MASK | NFS_VERS_MASK); + vers |= NFS3_REQUESTED; +- } else if (strncmp("vers=2", cp, o_len) == 0 || +- strncmp("nfsvers=2", cp, o_len) == 0) { ++ } else if (_strncmp("vers=2", cp, o_len) == 0 || ++ _strncmp("nfsvers=2", cp, o_len) == 0) { + vers &= ~(NFS4_VERS_MASK | NFS_VERS_MASK); + vers |= NFS2_REQUESTED; + } else if (strstr(cp, "port=") == cp && +@@ -164,16 +164,16 @@ int mount_mount(struct autofs_point *ap, + if (port < 0) + port = 0; + port_opt = cp; +- } else if (strncmp("proto=udp", cp, o_len) == 0 || +- strncmp("udp", cp, o_len) == 0) { ++ } else if (_strncmp("proto=udp", cp, o_len) == 0 || ++ _strncmp("udp", cp, o_len) == 0) { + vers &= ~TCP_SUPPORTED; +- } else if (strncmp("proto=tcp", cp, o_len) == 0 || +- strncmp("tcp", cp, o_len) == 0) { ++ } else if (_strncmp("proto=tcp", cp, o_len) == 0 || ++ _strncmp("tcp", cp, o_len) == 0) { + vers &= ~UDP_SUPPORTED; + } + /* Check for options that also make sense + with bind mounts */ +- else if (strncmp("ro", cp, o_len) == 0) ++ else if (_strncmp("ro", cp, o_len) == 0) + ro = 1; + /* and jump over trailing white space */ + memcpy(nfsp, cp, comma - cp + 1); +--- autofs-5.0.7.orig/modules/parse_sun.c ++++ autofs-5.0.7/modules/parse_sun.c +@@ -549,29 +549,29 @@ static int sun_mount(struct autofs_point + while (*comma != '\0' && *comma != ',') + comma++; + +- if (strncmp("fstype=", cp, 7) == 0) { ++ if (_strncmp("fstype=", cp, 7) == 0) { + int typelen = comma - (cp + 7); + fstype = alloca(typelen + 1); + memcpy(fstype, cp + 7, typelen); + fstype[typelen] = '\0'; +- } else if (strncmp("nonstrict", cp, 9) == 0) { ++ } else if (_strncmp("nonstrict", cp, 9) == 0) { + nonstrict = 1; +- } else if (strncmp("strict", cp, 6) == 0) { ++ } else if (_strncmp("strict", cp, 6) == 0) { + nonstrict = 0; +- } else if (strncmp("nobrowse", cp, 8) == 0 || +- strncmp("browse", cp, 6) == 0 || +- strncmp("timeout=", cp, 8) == 0) { ++ } else if (_strncmp("nobrowse", cp, 8) == 0 || ++ _strncmp("browse", cp, 6) == 0 || ++ _strncmp("timeout=", cp, 8) == 0) { + if (strcmp(fstype, "autofs") == 0 || + strstr(cp, "fstype=autofs")) { + memcpy(np, cp, comma - cp + 1); + np += comma - cp + 1; + } +- } else if (strncmp("no-use-weight-only", cp, 18) == 0) { ++ } else if (_strncmp("no-use-weight-only", cp, 18) == 0) { + use_weight_only = -1; +- } else if (strncmp("use-weight-only", cp, 15) == 0) { ++ } else if (_strncmp("use-weight-only", cp, 15) == 0) { + use_weight_only = MOUNT_FLAG_USE_WEIGHT_ONLY; +- } else if (strncmp("bg", cp, 2) == 0 || +- strncmp("nofg", cp, 4) == 0) { ++ } else if (_strncmp("bg", cp, 2) == 0 || ++ _strncmp("nofg", cp, 4) == 0) { + continue; + } else { + memcpy(np, cp, comma - cp + 1); diff --git a/SOURCES/autofs-5.0.8-fix-symlink-expire.patch b/SOURCES/autofs-5.0.8-fix-symlink-expire.patch new file mode 100644 index 0000000..606e7d5 --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-symlink-expire.patch @@ -0,0 +1,66 @@ +autofs-5.0.8 - fix symlink expire + +From: Ian Kent + +The expire code uses the list of mounts to decide if additional expire +check requests should be sent to the kernel. This doesn't take into +account the possibility there could be symlinks that might be able to +be expired. + +count_mounts() does count symlinks so use that only when working out +how many expire requests should be sent. +--- + CHANGELOG | 1 + + daemon/indirect.c | 22 ++++++++++------------ + 2 files changed, 11 insertions(+), 12 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -86,6 +86,7 @@ + - fix undefined authtype_requires_creds err if ldap enabled but without sasl. + - pass map_source as function paramter where possible. + - check for bind onto self in mount_bind.c. ++- fix symlink expire. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/indirect.c ++++ autofs-5.0.7/daemon/indirect.c +@@ -388,6 +388,7 @@ void *expire_proc_indirect(void *arg) + struct expire_args ec; + unsigned int now; + int offsets, submnts, count; ++ int retries; + int ioctlfd, cur_state; + int status, ret, left; + +@@ -533,20 +534,17 @@ void *expire_proc_indirect(void *arg) + + /* + * If there are no more real mounts left we could still +- * have some offset mounts with no '/' offset so we need to +- * umount them here. ++ * have some offset mounts with no '/' offset or symlinks ++ * so we need to umount or unlink them here. + */ +- if (mnts) { +- int retries; +- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); +- retries = (count_mounts(ap->logopt, ap->path, ap->dev) + 1); +- while (retries--) { +- ret = ops->expire(ap->logopt, ap->ioctlfd, ap->path, now); +- if (ret) +- left++; +- } +- pthread_setcancelstate(cur_state, NULL); ++ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); ++ retries = (count_mounts(ap->logopt, ap->path, ap->dev) + 1); ++ while (retries--) { ++ ret = ops->expire(ap->logopt, ap->ioctlfd, ap->path, now); ++ if (ret) ++ left++; + } ++ pthread_setcancelstate(cur_state, NULL); + pthread_cleanup_pop(1); + + count = offsets = submnts = 0; diff --git a/SOURCES/autofs-5.0.8-fix-symlink-fail-message-in-mount_bind-c.patch b/SOURCES/autofs-5.0.8-fix-symlink-fail-message-in-mount_bind-c.patch new file mode 100644 index 0000000..3c677c9 --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-symlink-fail-message-in-mount_bind-c.patch @@ -0,0 +1,31 @@ +autofs-5.0.8 - fix symlink fail message in mount_bind.c + +From: Ian Kent + + +--- + CHANGELOG | 1 + + modules/mount_bind.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -78,6 +78,7 @@ + - fix max() declaration. + - setup program map env from macro table. + - add short host name standard marco variable. ++- fix symlink fail message in mount_bind.c. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/mount_bind.c ++++ autofs-5.0.7/modules/mount_bind.c +@@ -206,7 +206,7 @@ int mount_mount(struct autofs_point *ap, + if (symlink(what, fullpath) && errno != EEXIST) { + error(ap->logopt, + MODPREFIX +- "failed to create local mount %s -> %s", ++ "failed to create symlink %s -> %s", + fullpath, what); + if ((ap->flags & MOUNT_FLAG_GHOST) && !status) + if (mkdir_path(fullpath, 0555) && errno != EEXIST) { diff --git a/SOURCES/autofs-5.0.8-fix-undefined-authtype_requires_creds-err-if-ldap-en.patch b/SOURCES/autofs-5.0.8-fix-undefined-authtype_requires_creds-err-if-ldap-en.patch new file mode 100644 index 0000000..cd14bca --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-undefined-authtype_requires_creds-err-if-ldap-en.patch @@ -0,0 +1,48 @@ +autofs-5.0.8 - fix undefined authtype_requires_creds err if ldap enabled but without sasl + +From: Lan Yixun (dlan) + +This patch is moving "WITH_SASL" into authtype_requires_creds function +make it return 0 if sasl not enabled, which mean authtype_requires_creds is not enabled + +https://bugs.gentoo.org/show_bug.cgi?id=489128 +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 4 ++-- + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -83,6 +83,7 @@ + - check for existing offset mount before mounting. + - fix cache readlock not taken on lookup. + - fix compilation of lookup_ldap.c without sasl. ++- fix undefined authtype_requires_creds err if ldap enabled but without sasl. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -813,20 +813,20 @@ int get_property(unsigned logopt, xmlNod + return 0; + } + +-#ifdef WITH_SASL + /* + * For plain text, login and digest-md5 authentication types, we need + * user and password credentials. + */ + int authtype_requires_creds(const char *authtype) + { ++#ifdef WITH_SASL + if (!strncmp(authtype, "PLAIN", strlen("PLAIN")) || + !strncmp(authtype, "DIGEST-MD5", strlen("DIGEST-MD5")) || + !strncmp(authtype, "LOGIN", strlen("LOGIN"))) + return 1; ++#endif + return 0; + } +-#endif + + /* + * Returns: diff --git a/SOURCES/autofs-5.0.8-fix-variable-substitution-description.patch b/SOURCES/autofs-5.0.8-fix-variable-substitution-description.patch new file mode 100644 index 0000000..e845779 --- /dev/null +++ b/SOURCES/autofs-5.0.8-fix-variable-substitution-description.patch @@ -0,0 +1,44 @@ +autofs-5.0.8 - fix variable substitution description + +From: Ian Kent + +The desription about Variable substitution in autofs(5) says that +translation is done on the key and location fields which is not +correct. + +Expecting to be able to receive a key from the kernel that +contains variables to be substituted doesn't make sense and +to be able to use map keys with substitution would mean a full +map scan for every lookup for all map sources. That is not +unacceptable for large maps. +--- + CHANGELOG | 1 + + man/autofs.5 | 7 ++++--- + 2 files changed, 5 insertions(+), 3 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -101,6 +101,7 @@ + - fix inconsistent error returns in handle_packet_missing_direct(). + - simple coverity fixes. + - fixes for samples/auto.master. ++- fix variable substitution description. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/man/autofs.5 ++++ autofs-5.0.7/man/autofs.5 +@@ -157,9 +157,10 @@ The special character '&' will be replac + in the example above, a lookup for the key 'foo' would yield a mount + of server:/export/home/foo. + .SS Variable Substitution +-The following special variables will be substituted in the key and location +-fields of an automounter map if prefixed with $ as customary from shell +-scripts (Curly braces can be used to separate the field name): ++The following special variables will be substituted in the location ++field of an automounter map entry if prefixed with $ as customary ++from shell scripts (curly braces can be used to separate the field ++name): + .sp + .RS +.2i + .ta 1.5i diff --git a/SOURCES/autofs-5.0.8-fixes-for-samples-auto_master.patch b/SOURCES/autofs-5.0.8-fixes-for-samples-auto_master.patch new file mode 100644 index 0000000..6829c13 --- /dev/null +++ b/SOURCES/autofs-5.0.8-fixes-for-samples-auto_master.patch @@ -0,0 +1,59 @@ +autofs-5.0.8 - fixes for samples/auto.master + +From: Vincent McIntyre + +Replace description that described regular automount maps, not +master maps. Add a note about the format of included files. +Clarify what happens to master map options not consumed by +'mount'. + +Signed-off-by: +--- + CHANGELOG | 1 + + man/auto.master.5.in | 2 +- + samples/auto.master | 7 ++++--- + 3 files changed, 6 insertions(+), 4 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -100,6 +100,7 @@ + - dont ignore null cache entries on multi mount umount. + - fix inconsistent error returns in handle_packet_missing_direct(). + - simple coverity fixes. ++- fixes for samples/auto.master. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/man/auto.master.5.in ++++ autofs-5.0.7/man/auto.master.5.in +@@ -139,7 +139,7 @@ the \fBdn\fP of an LDAP entry for maps o + .br + Any remaining command line arguments without leading dashes (\-) are + taken as options (\fI\-o\fP) to \fBmount\fP. Arguments with leading +-dashes are considered options for the maps. ++dashes are considered options for the maps and are passed to automount (8). + .sp + The \fBsun\fP format supports the following options: + .RS +--- autofs-5.0.7.orig/samples/auto.master ++++ autofs-5.0.7/samples/auto.master +@@ -1,8 +1,8 @@ + # + # Sample auto.master file +-# This is an automounter map and it has the following format +-# key [ -mount-options-separated-by-comma ] location +-# For details of the format look at autofs(5). ++# This is a 'master' automounter map and it has the following format: ++# mount-point [map-type[,format]:]map [options] ++# For details of the format look at auto.master(5). + # + /misc /etc/auto.misc + # +@@ -13,6 +13,7 @@ + /net -hosts + # + # Include /etc/auto.master.d/*.autofs ++# The included files must conform to the format of this file. + # + +dir:/etc/auto.master.d + # diff --git a/SOURCES/autofs-5.0.8-make-autofs-5-consistent-with-auto-master-5.patch b/SOURCES/autofs-5.0.8-make-autofs-5-consistent-with-auto-master-5.patch new file mode 100644 index 0000000..4eeb5db --- /dev/null +++ b/SOURCES/autofs-5.0.8-make-autofs-5-consistent-with-auto-master-5.patch @@ -0,0 +1,167 @@ +autofs-5.0.8 - make autofs(5) consistent with auto.master(5) + +From: Ian Kent + +The presentation in autofs(5) isn't the same as that in auto.master(5). +--- + CHANGELOG | 1 + + man/auto.master.5.in | 18 +++++++++++------- + man/autofs.5 | 41 +++++++++++++++++++++++++++-------------- + 3 files changed, 39 insertions(+), 21 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -93,6 +93,7 @@ + - change walk_tree() to take ap. + - add negative cache lookup to hesiod lookup. + - fix external env configure. ++- make autofs(5) consistent with auto.master(5). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/man/auto.master.5.in ++++ autofs-5.0.7/man/auto.master.5.in +@@ -38,14 +38,14 @@ Access to mounts in maps is governed by + .P + For direct maps the mount point is always specified as: + .P +-/- ++.BR /- + .P + and the key used within the direct map is the full path to the mount point. The direct map + may have multiple entries in the master map. + .P + For indirect maps access is by using the path scheme: + .P +-.RI / mount-point / key ++.BR /mount-point/key + .P + where + .I mount-point +@@ -57,7 +57,9 @@ map given in the entry (See + .P + Additionally, a map may be included from its source as if it were itself + present in the master map by including a line of the form: +-.BR +\ [ maptype , format :] map [ options ] ++.P ++.BR + [ maptype [, format ]:] map\ [ options ] ++.P + and + .BR automount (8) + will process the map according to the specification described below for +@@ -73,14 +75,14 @@ which contains options to be applied to + .P + The format of a master map entry is: + .TP +-.IR mount-point\ [ map-type [, format ]:] map\ [ options ] ++.BR mount-point\ [ map-type [, format ]:] map\ [ options ] + .TP +-\fBmount-point\fP ++.B mount-point + Base location for the \fBautofs\fP filesystem to be mounted. For + indirect maps this directory will be created (as with \fBmkdir \-p\fP) + and is removed when the \fBautofs\fP filesystem is umounted. + .TP +-\fBmap-type\fP ++.B map-type + Type of map used for this mount point. The following are + valid map types: + .RS +@@ -133,7 +135,8 @@ for maps of types \fBfile\fP, \fBdir\fP, + in the case for maps of type \fByp\fP, \fBnisplus\fP, or \fBhesiod\fP or + the \fBdn\fP of an LDAP entry for maps of type \fBldap\fP. + .TP +-\fBoptions\fP ++.B options ++.br + Any remaining command line arguments without leading dashes (\-) are + taken as options (\fI\-o\fP) to \fBmount\fP. Arguments with leading + dashes are considered options for the maps. +@@ -287,6 +290,7 @@ it will used for subsequent lookups. + There are three common schemas in use: + .TP + .I nisMap ++.br + Entries in the \fBnisMap\fP schema are \fBnisObject\fP objects in + the specified subtree, where the \fBcn\fP attribute is the key + (the wildcard key is "/"), and the \fBnisMapEntry\fP attribute +--- autofs-5.0.7.orig/man/autofs.5 ++++ autofs-5.0.7/man/autofs.5 +@@ -22,42 +22,56 @@ This is a description of the text file f + these files may exist. All empty lines or lines beginning with # are + ignored. The basic format of one line in such maps is: + .P +-.BI "key [" -options "] location" +- +-.SS key ++.BR key\ [ -options ]\ location ++.TP ++.B key ++.br + For indirect mounts this is the part of the path name between the mount point + and the path into the filesystem when it is mounted. Usually you can think about the + key as a sub-directory name below the autofs managed mount point. + + For direct mounts this is the full path of each mount point. This map is always + associated with the /- mount point in the master map. +- +-.SS options ++.TP ++.B options ++.br + Zero or more options may be given. Options can also be given in the + .B auto.master + file in which case both values are cumulative (this is a difference + from SunOS). The options are a list of comma separated options as + customary for the + .BR mount (8) +-command. There are two special options +-.I -fstype= +-used to specify a filesystem type if the filesystem is not of the default ++command. ++ ++There are several special options ++.RS ++.TP ++.B -fstype= ++.br ++is used to specify a filesystem type if the filesystem is not of the default + NFS type. This option is processed by the automounter and not by the mount + command. +-.I -strict ++.TP ++.B -strict ++.br + is used to treat errors when mounting file systems as fatal. This is important when + multiple file systems should be mounted (`multi-mounts'). If this option + is given, no file system is mounted at all if at least one file system + can't be mounted. +-.I -use-weight-only ++.TP ++.B -use-weight-only ++.br + is used to make the weight the sole factor in selecting a server when multiple + servers are present in a map entry. + and +-.I -no-use-weight-only ++.TP ++.B -no-use-weight-only ++.br + can be used to negate the option if it is present in the master map entry + for the map but is not wanted for the given mount. +- +-.SS location ++.RE ++.TP ++.B location + The location specifies from where the file system is to be mounted. In the + most cases this will be an NFS volume and the usual notation + .I host:pathname +@@ -227,7 +241,6 @@ Anything else is questionable and unsupp + host1(3),host:/blah + .fi + .RE +-.sp + .SH UNSUPPORTED + This version of the automounter supports direct maps stored in FILE, NIS, NISPLUS + and LDAP only. diff --git a/SOURCES/autofs-5.0.8-pass-map_source-as-function-paramter-where-possible.patch b/SOURCES/autofs-5.0.8-pass-map_source-as-function-paramter-where-possible.patch new file mode 100644 index 0000000..20faa6f --- /dev/null +++ b/SOURCES/autofs-5.0.8-pass-map_source-as-function-paramter-where-possible.patch @@ -0,0 +1,538 @@ +autofs-5.0.8 - pass map_source as function paramter where possible + +From: Ian Kent + +Some unnecessary complexity has been added along the way when passing +the map source to functions in lookup modules. Improve that where +possible. +--- + CHANGELOG | 1 + modules/lookup_file.c | 82 +++++++++++++++-------------------------------- + modules/lookup_ldap.c | 37 ++++++--------------- + modules/lookup_nisplus.c | 36 ++++---------------- + modules/lookup_yp.c | 36 ++++---------------- + 5 files changed, 56 insertions(+), 136 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -84,6 +84,7 @@ + - fix cache readlock not taken on lookup. + - fix compilation of lookup_ldap.c without sasl. + - fix undefined authtype_requires_creds err if ldap enabled but without sasl. ++- pass map_source as function paramter where possible. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_file.c ++++ autofs-5.0.7/modules/lookup_file.c +@@ -529,21 +529,17 @@ static int check_self_include(const char + + static struct map_source * + prepare_plus_include(struct autofs_point *ap, ++ struct map_source *source, + time_t age, char *key, unsigned int inc, + struct lookup_context *ctxt) + { +- struct map_source *current; +- struct map_source *source; ++ struct map_source *new; + struct map_type_info *info; + const char *argv[2]; + char **tmp_argv, **tmp_opts; + int argc; + char *buf; + +- current = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + /* + * TODO: + * Initially just consider the passed in key to be a simple map +@@ -596,21 +592,21 @@ prepare_plus_include(struct autofs_point + } + argc += ctxt->opts_argc; + +- source = master_find_source_instance(current, +- info->type, info->format, +- argc, (const char **) tmp_argv); +- if (source) { ++ new = master_find_source_instance(source, ++ info->type, info->format, ++ argc, (const char **) tmp_argv); ++ if (new) { + /* + * Make sure included map age is in sync with its owner + * or we could incorrectly wipe out its entries. + */ +- source->age = age; +- source->stale = 1; ++ new->age = age; ++ new->stale = 1; + } else { +- source = master_add_source_instance(current, +- info->type, info->format, age, +- argc, (const char **) tmp_argv); +- if (!source) { ++ new = master_add_source_instance(source, ++ info->type, info->format, age, ++ argc, (const char **) tmp_argv); ++ if (!new) { + free_argv(argc, (const char **) tmp_argv); + free_map_type_info(info); + free(buf); +@@ -620,14 +616,14 @@ prepare_plus_include(struct autofs_point + } + free_argv(argc, (const char **) tmp_argv); + +- source->depth = current->depth + 1; ++ new->depth = source->depth + 1; + if (inc) +- source->recurse = 1; ++ new->recurse = 1; + + free_map_type_info(info); + free(buf); + +- return source; ++ return new; + } + + int lookup_read_map(struct autofs_point *ap, time_t age, void *context) +@@ -689,10 +685,8 @@ int lookup_read_map(struct autofs_point + + inc = check_self_include(key, ctxt); + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- inc_source = prepare_plus_include(ap, age, key, inc, ctxt); ++ inc_source = prepare_plus_include(ap, source, ++ age, key, inc, ctxt); + if (!inc_source) { + debug(ap->logopt, + "failed to select included map %s", key); +@@ -731,10 +725,10 @@ int lookup_read_map(struct autofs_point + } + + static int lookup_one(struct autofs_point *ap, ++ struct map_source *source, + const char *key, int key_len, + struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + char mkey[KEY_MAX_LEN + 1]; + char mapent[MAPENT_MAX_LEN + 1]; +@@ -743,10 +737,6 @@ static int lookup_one(struct autofs_poin + unsigned int k_len, m_len; + int entry, ret; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + + f = open_fopen_r(ctxt->mapname); +@@ -773,10 +763,8 @@ static int lookup_one(struct autofs_poin + + inc = check_self_include(mkey, ctxt); + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- inc_source = prepare_plus_include(ap, age, mkey, inc, ctxt); ++ inc_source = prepare_plus_include(ap, source, ++ age, mkey, inc, ctxt); + if (!inc_source) { + debug(ap->logopt, + MODPREFIX +@@ -837,9 +825,9 @@ static int lookup_one(struct autofs_poin + return CHE_MISSING; + } + +-static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt) ++static int lookup_wild(struct autofs_point *ap, ++ struct map_source *source, struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + char mkey[KEY_MAX_LEN + 1]; + char mapent[MAPENT_MAX_LEN + 1]; +@@ -848,10 +836,6 @@ static int lookup_wild(struct autofs_poi + unsigned int k_len, m_len; + int entry, ret; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + + f = open_fopen_r(ctxt->mapname); +@@ -895,24 +879,17 @@ static int lookup_wild(struct autofs_poi + } + + static int check_map_indirect(struct autofs_point *ap, ++ struct map_source *source, + char *key, int key_len, + struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + struct mapent *exists; + int ret = CHE_OK; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- ret = lookup_one(ap, key, key_len, ctxt); ++ ret = lookup_one(ap, source, key, key_len, ctxt); + if (ret == CHE_COMPLETED) + return NSS_STATUS_COMPLETED; + +@@ -935,10 +912,7 @@ static int check_map_indirect(struct aut + struct mapent *we; + int wild = CHE_MISSING; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- wild = lookup_wild(ap, ctxt); ++ wild = lookup_wild(ap, source, ctxt); + /* + * Check for map change and update as needed for + * following cache lookup. +@@ -1072,10 +1046,8 @@ int lookup_mount(struct autofs_point *ap + if (!lkp_key) + return NSS_STATUS_UNKNOWN; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); ++ status = check_map_indirect(ap, source, ++ lkp_key, strlen(lkp_key), ctxt); + free(lkp_key); + if (status) { + if (status == NSS_STATUS_COMPLETED) +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -2321,20 +2321,16 @@ next: + + + static int read_one_map(struct autofs_point *ap, ++ struct map_source *source, + struct lookup_context *ctxt, + time_t age, int *result_ldap) + { +- struct map_source *source; + struct ldap_search_params sp; + char buf[MAX_ERR_BUF]; + char *class, *info, *entry; + char *attrs[3]; + int rv, l; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + /* + * If we don't need to create directories then there's no use + * reading the map. We always need to read the whole map for +@@ -2453,11 +2449,16 @@ static int read_one_map(struct autofs_po + int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + { + struct lookup_context *ctxt = (struct lookup_context *) context; ++ struct map_source *source; + int rv = LDAP_SUCCESS; + int ret, cur_state; + ++ source = ap->entry->current; ++ ap->entry->current = NULL; ++ master_source_current_signal(ap->entry); ++ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); +- ret = read_one_map(ap, ctxt, age, &rv); ++ ret = read_one_map(ap, source, ctxt, age, &rv); + if (ret != NSS_STATUS_SUCCESS) { + switch (rv) { + case LDAP_SIZELIMIT_EXCEEDED: +@@ -2474,10 +2475,9 @@ int lookup_read_map(struct autofs_point + return ret; + } + +-static int lookup_one(struct autofs_point *ap, ++static int lookup_one(struct autofs_point *ap, struct map_source *source, + char *qKey, int qKey_len, struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + int rv, i, l, ql, count; + char buf[MAX_ERR_BUF]; +@@ -2496,10 +2496,6 @@ static int lookup_one(struct autofs_poin + unsigned int wild = 0; + int ret = CHE_MISSING; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + + if (ctxt == NULL) { +@@ -2834,27 +2830,20 @@ next: + } + + static int check_map_indirect(struct autofs_point *ap, ++ struct map_source *source, + char *key, int key_len, + struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + struct mapent *me; + time_t now = time(NULL); + time_t t_last_read; + int ret, cur_state; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); +- ret = lookup_one(ap, key, key_len, ctxt); ++ ret = lookup_one(ap, source, key, key_len, ctxt); + if (ret == CHE_FAIL) { + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_NOTFOUND; +@@ -2974,10 +2963,8 @@ int lookup_mount(struct autofs_point *ap + if (!lkp_key) + return NSS_STATUS_UNKNOWN; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); ++ status = check_map_indirect(ap, source, ++ lkp_key, strlen(lkp_key), ctxt); + free(lkp_key); + if (status) + return status; +--- autofs-5.0.7.orig/modules/lookup_nisplus.c ++++ autofs-5.0.7/modules/lookup_nisplus.c +@@ -267,10 +267,10 @@ int lookup_read_map(struct autofs_point + } + + static int lookup_one(struct autofs_point *ap, ++ struct map_source *source, + const char *key, int key_len, + struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + char *tablename; + nis_result *result; +@@ -280,10 +280,6 @@ static int lookup_one(struct autofs_poin + int ret, cur_state; + char buf[MAX_ERR_BUF]; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); +@@ -326,9 +322,9 @@ static int lookup_one(struct autofs_poin + return ret; + } + +-static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt) ++static int lookup_wild(struct autofs_point *ap, ++ struct map_source *source, struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + char *tablename; + nis_result *result; +@@ -338,10 +334,6 @@ static int lookup_wild(struct autofs_poi + int ret, cur_state; + char buf[MAX_ERR_BUF]; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); +@@ -383,27 +375,20 @@ static int lookup_wild(struct autofs_poi + } + + static int check_map_indirect(struct autofs_point *ap, ++ struct map_source *source, + char *key, int key_len, + struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + struct mapent *me, *exists; + time_t now = time(NULL); + time_t t_last_read; + int ret = 0; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- + /* check map and if change is detected re-read map */ +- ret = lookup_one(ap, key, key_len, ctxt); ++ ret = lookup_one(ap, source, key, key_len, ctxt); + if (ret == CHE_FAIL) + return NSS_STATUS_NOTFOUND; + +@@ -452,10 +437,7 @@ static int check_map_indirect(struct aut + int wild = CHE_MISSING; + struct mapent *we; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- wild = lookup_wild(ap, ctxt); ++ wild = lookup_wild(ap, source, ctxt); + /* + * Check for map change and update as needed for + * following cache lookup. +@@ -553,10 +535,8 @@ int lookup_mount(struct autofs_point *ap + if (!lkp_key) + return NSS_STATUS_UNKNOWN; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); ++ status = check_map_indirect(ap, source, ++ lkp_key, strlen(lkp_key), ctxt); + if (status) + return status; + } +--- autofs-5.0.7.orig/modules/lookup_yp.c ++++ autofs-5.0.7/modules/lookup_yp.c +@@ -377,10 +377,10 @@ int lookup_read_map(struct autofs_point + } + + static int lookup_one(struct autofs_point *ap, ++ struct map_source *source, + const char *key, int key_len, + struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + char *mapname; + char *mapent; +@@ -388,10 +388,6 @@ static int lookup_one(struct autofs_poin + time_t age = time(NULL); + int ret; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + + mapname = alloca(strlen(ctxt->mapname) + 1); +@@ -436,9 +432,9 @@ static int lookup_one(struct autofs_poin + return ret; + } + +-static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt) ++static int lookup_wild(struct autofs_point *ap, ++ struct map_source *source, struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + char *mapname; + char *mapent; +@@ -446,10 +442,6 @@ static int lookup_wild(struct autofs_poi + time_t age = time(NULL); + int ret; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + + mapname = alloca(strlen(ctxt->mapname) + 1); +@@ -489,26 +481,19 @@ static int lookup_wild(struct autofs_poi + } + + static int check_map_indirect(struct autofs_point *ap, ++ struct map_source *source, + char *key, int key_len, + struct lookup_context *ctxt) + { +- struct map_source *source; + struct mapent_cache *mc; + struct mapent *exists; + unsigned int map_order; + int ret = 0; + +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- + mc = source->mc; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- + /* check map and if change is detected re-read map */ +- ret = lookup_one(ap, key, key_len, ctxt); ++ ret = lookup_one(ap, source, key, key_len, ctxt); + if (ret == CHE_FAIL) + return NSS_STATUS_NOTFOUND; + +@@ -556,10 +541,7 @@ static int check_map_indirect(struct aut + struct mapent *we; + int wild = CHE_MISSING; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- wild = lookup_wild(ap, ctxt); ++ wild = lookup_wild(ap, source, ctxt); + /* + * Check for map change and update as needed for + * following cache lookup. +@@ -657,10 +639,8 @@ int lookup_mount(struct autofs_point *ap + if (!lkp_key) + return NSS_STATUS_UNKNOWN; + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); ++ status = check_map_indirect(ap, source, ++ lkp_key, strlen(lkp_key), ctxt); + free(lkp_key); + if (status) + return status; diff --git a/SOURCES/autofs-5.0.8-remove-macro-debug-prints.patch b/SOURCES/autofs-5.0.8-remove-macro-debug-prints.patch new file mode 100644 index 0000000..d78e059 --- /dev/null +++ b/SOURCES/autofs-5.0.8-remove-macro-debug-prints.patch @@ -0,0 +1,23 @@ +autofs-5.0.8 - remove macro debug prints + +From: Ian Kent + +Remove a couple of missed debugging prints from macro_setenv(); +--- + lib/macros.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/lib/macros.c b/lib/macros.c +index d7c392f..c858f41 100644 +--- a/lib/macros.c ++++ b/lib/macros.c +@@ -437,9 +437,6 @@ void macro_setenv(struct substvar *table) + sv = sv->next; + } + +- error(LOGOPT_ANY, "table %p", table); +- dump_table(table); +- + /* Next set environment from the local table */ + while (lv) { + if (lv->def) diff --git a/SOURCES/autofs-5.0.8-remove-stale-debug-message.patch b/SOURCES/autofs-5.0.8-remove-stale-debug-message.patch new file mode 100644 index 0000000..d317f4c --- /dev/null +++ b/SOURCES/autofs-5.0.8-remove-stale-debug-message.patch @@ -0,0 +1,21 @@ +autofs-5.0.8 - remove stale debug message + +From: Ian Kent + + +--- + modules/parse_sun.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/modules/parse_sun.c b/modules/parse_sun.c +index 8e5c60c..6f0e3c9 100644 +--- a/modules/parse_sun.c ++++ b/modules/parse_sun.c +@@ -1397,7 +1397,6 @@ int parse_mount(struct autofs_point *ap, const char *name, + if (!l) { + if (!(strstr(myoptions, "fstype=autofs") && + strstr(myoptions, "hosts"))) { +- error(LOGOPT_ANY, "I think I'm a hosts map? l %d", l); + cache_delete_offset_list(mc, name); + cache_multi_unlock(me); + cache_unlock(mc); diff --git a/SOURCES/autofs-5.0.8-simple-coverity-fixes.patch b/SOURCES/autofs-5.0.8-simple-coverity-fixes.patch new file mode 100644 index 0000000..4f9d63f --- /dev/null +++ b/SOURCES/autofs-5.0.8-simple-coverity-fixes.patch @@ -0,0 +1,94 @@ +autofs-5.0.8 - simple coverity fixes + +From: Ian Kent + +Add a couple of simple corrections reported by Coverity. +--- + CHANGELOG | 1 + + daemon/automount.c | 6 ------ + daemon/lookup.c | 3 ++- + modules/lookup_hosts.c | 3 ++- + modules/lookup_program.c | 3 ++- + modules/mount_bind.c | 4 ++-- + 6 files changed, 9 insertions(+), 11 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -99,6 +99,7 @@ + - fix lookup_nss_mount() map lookup. + - dont ignore null cache entries on multi mount umount. + - fix inconsistent error returns in handle_packet_missing_direct(). ++- simple coverity fixes. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/automount.c ++++ autofs-5.0.7/daemon/automount.c +@@ -1776,12 +1776,6 @@ static void show_build_info(void) + #ifdef ENABLE_FORCED_SHUTDOWN + printf("ENABLE_FORCED_SHUTDOWN "); + count = count + 23; +- +- if (count > 60) { +- printf("\n "); +- count = 0; +- } +- + #endif + + #ifdef ENABLE_IGNORE_BUSY_MOUNTS +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -959,7 +959,8 @@ static void update_negative_cache(struct + rv = cache_update(map->mc, map, name, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(map->mc, name); +- me->status = now + ap->negative_timeout; ++ if (me) ++ me->status = now + ap->negative_timeout; + } + cache_unlock(map->mc); + } +--- autofs-5.0.7.orig/modules/lookup_hosts.c ++++ autofs-5.0.7/modules/lookup_hosts.c +@@ -161,7 +161,8 @@ static int do_parse_mount(struct autofs_ + rv = cache_update(mc, source, name, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, name); +- me->status = now + ap->negative_timeout; ++ if (me) ++ me->status = now + ap->negative_timeout; + } + cache_unlock(mc); + return NSS_STATUS_TRYAGAIN; +--- autofs-5.0.7.orig/modules/lookup_program.c ++++ autofs-5.0.7/modules/lookup_program.c +@@ -459,7 +459,8 @@ out_free: + rv = cache_update(mc, source, name, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, name); +- me->status = now + ap->negative_timeout; ++ if (me) ++ me->status = now + ap->negative_timeout; + } + cache_unlock(mc); + return NSS_STATUS_TRYAGAIN; +--- autofs-5.0.7.orig/modules/mount_bind.c ++++ autofs-5.0.7/modules/mount_bind.c +@@ -214,14 +214,14 @@ int mount_mount(struct autofs_point *ap, + MODPREFIX + "failed to create symlink %s -> %s", + fullpath, what); +- if ((ap->flags & MOUNT_FLAG_GHOST) && !status) ++ if ((ap->flags & MOUNT_FLAG_GHOST) && !status) { + if (mkdir_path(fullpath, 0555) && errno != EEXIST) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(ap->logopt, + MODPREFIX "mkdir_path %s failed: %s", + fullpath, estr); + } +- else { ++ } else { + if (ap->type == LKP_INDIRECT) + rmdir_path(ap, fullpath, ap->dev); + } diff --git a/SOURCES/autofs-5.0.8-use-open-instead-of-access.patch b/SOURCES/autofs-5.0.8-use-open-instead-of-access.patch new file mode 100644 index 0000000..809b905 --- /dev/null +++ b/SOURCES/autofs-5.0.8-use-open-instead-of-access.patch @@ -0,0 +1,127 @@ +autofs-5.0.8 - use open(2) instead of access(2) + +From: Ian Kent + +The access(2) system call has been used to trigger dependednt automounts +in the target path when mounting. But access(2) no longer triggers the +dependednt mounts. + +So use open(2) with flag O_DIRECTORY which will trigger these mounts. +--- + CHANGELOG | 1 + + daemon/spawn.c | 30 ++++++++++++++++++------------ + 2 files changed, 19 insertions(+), 12 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -104,6 +104,7 @@ + - fix variable substitution description. + - fix incorrect append options description in README.v5-release. + - fix mistake in assignment. ++- use open(2) instead of access(2) to trigger dependent mounts. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/spawn.c ++++ autofs-5.0.7/daemon/spawn.c +@@ -32,7 +32,7 @@ static pthread_mutex_t spawn_mutex = PTH + + #define SPAWN_OPT_NONE 0x0000 + #define SPAWN_OPT_LOCK 0x0001 +-#define SPAWN_OPT_ACCESS 0x0002 ++#define SPAWN_OPT_OPEN 0x0002 + + #define MTAB_LOCK_RETRIES 3 + +@@ -126,7 +126,7 @@ static int do_spawn(unsigned logopt, uns + int errp, errn; + int cancel_state; + unsigned int use_lock = options & SPAWN_OPT_LOCK; +- unsigned int use_access = options & SPAWN_OPT_ACCESS; ++ unsigned int use_open = options & SPAWN_OPT_OPEN; + sigset_t allsigs, tmpsig, oldsig; + struct thread_stdenv_vars *tsv; + pid_t euid = 0; +@@ -166,6 +166,8 @@ static int do_spawn(unsigned logopt, uns + /* what to mount must always be second last */ + while (*pargv++) + loc++; ++ if (loc <= 3) ++ goto done; + loc -= 2; + + /* +@@ -176,7 +178,9 @@ static int do_spawn(unsigned logopt, uns + * + * I hope host names are never allowed "/" as first char + */ +- if (use_access && *(argv[loc]) == '/') { ++ if (use_open && *(argv[loc]) == '/') { ++ int fd; ++ + pid_t pgrp = getpgrp(); + + /* +@@ -192,19 +196,21 @@ static int do_spawn(unsigned logopt, uns + /* + * Trigger the recursive mount. + * +- * Ignore the access(2) return code as there may be ++ * Ignore the open(2) return code as there may be + * multiple waiters for this mount and we need to +- * let the VFS handle access returns to each +- * individual waiter. ++ * let the VFS handle returns to each individual ++ * waiter. + */ +- access(argv[loc], F_OK); ++ fd = open(argv[loc], O_DIRECTORY); ++ if (fd != -1) ++ close(fd); + + seteuid(0); + setegid(0); + if (pgrp >= 0) + setpgid(0, pgrp); + } +- ++done: + execv(prog, (char *const *) argv); + _exit(255); /* execv() failed */ + } else { +@@ -327,7 +333,7 @@ int spawn_mount(unsigned logopt, ...) + #ifdef ENABLE_MOUNT_LOCKING + options = SPAWN_OPT_LOCK; + #else +- options = SPAWN_OPT_ACCESS; ++ options = SPAWN_OPT_OPEN; + #endif + + va_start(arg, logopt); +@@ -360,7 +366,7 @@ int spawn_mount(unsigned logopt, ...) + p = argv + 2; + } + while ((*p = va_arg(arg, char *))) { +- if (options == SPAWN_OPT_ACCESS && !strcmp(*p, "-t")) { ++ if (options == SPAWN_OPT_OPEN && !strcmp(*p, "-t")) { + *(++p) = va_arg(arg, char *); + if (!*p) + break; +@@ -429,7 +435,7 @@ int spawn_mount(unsigned logopt, ...) + + /* + * For bind mounts that depend on the target being mounted (possibly +- * itself an automount) we attempt to mount the target using an access ++ * itself an automount) we attempt to mount the target using an open(2) + * call. For this to work the location must be the second last arg. + * + * NOTE: If mount locking is enabled this type of recursive mount cannot +@@ -455,7 +461,7 @@ int spawn_bind_mount(unsigned logopt, .. + #ifdef ENABLE_MOUNT_LOCKING + options = SPAWN_OPT_LOCK; + #else +- options = SPAWN_OPT_ACCESS; ++ options = SPAWN_OPT_OPEN; + #endif + + /* diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-REDAME-amd-maps.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-REDAME-amd-maps.patch new file mode 100644 index 0000000..0cf52ab --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-REDAME-amd-maps.patch @@ -0,0 +1,142 @@ +autofs-5.0.9 - amd lookup add README.amd-maps + +From: Ian Kent + + +--- + README.amd-maps | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 126 insertions(+) + create mode 100644 README.amd-maps + +diff --git a/README.amd-maps b/README.amd-maps +new file mode 100644 +index 0000000..b31a7db +--- /dev/null ++++ b/README.amd-maps +@@ -0,0 +1,126 @@ ++ ++amd map parser ++============== ++ ++The ability to parse amd format maps has been added to autofs. ++ ++How to use amd maps in autofs ++----------------------------- ++ ++To add amd map parsing to autofs new "format" module has been added. ++To use this new map format module the existing master map syntax is ++used as described below. ++ ++The master map entry syntax is: ++ ++mount-point [map-type[,format]:]map [options] ++ ++For amd format maps this becomes: ++ ++/amd/mp   file,amd:amd.mp ++ ++which will use file as the map source and the amd format parser for ++the map. But see the section below on configuration below for how to ++eliminate the need to specify "map-type,format" in the master map. ++ ++Configuration sub-system changes ++-------------------------------- ++ ++The configuration sub-system has changed to accommodate the amd parser. ++See autofs.conf(5) for more information on format changes. ++ ++The configuration is now split into system initialization only ++configuration and the daemon configuration. Previously everything was ++located in the system initialization configuration file, but now the ++configuration is located in autofs.conf in the directory the distribution ++uses for the autofs configuration. ++ ++There is information about what amd configuration entries can be used ++in comments of the installed configuration so that's worth a look. ++ ++All that's needed to add an existing amd configuration to autofs is to ++add it below the autofs configuration. Apart from changing the amd ++"[ global ]" section name to "[ amd ]" nothing else should need to be ++changed. However, quite a few amd configuration options don't have ++meaning within autofs. When these options are seen it should be logged. ++ ++Be aware that, if the an old configuration exists and the configuration ++hasn't been updated after the installation, changes to the the old ++configuration will override changes to the new configuration because ++backward compatibility takes priority over the new implementation. ++ ++The amd per-map sections have two functions, to allow per-mount ++configuration, as it does in amd, and to allow master map entries to ++avoid the need to specify the "type,format" part of the master map ++entry so they can use the nsswitch map source functionality in the ++same way autofs master map entries do. ++ ++If a section for an amd mount is added below the global amd section ++using the mount point path (as is done in amd.conf) then autofs will ++know the map format is amd (it doesn't matter if there are no other ++configuration options in the mount point section). Since the map must ++be given in the master map entry the map_name option is not mandatory ++as it is in amd and will no be used. ++ ++If a mount point is present in the master map and the source of the ++map is nis then it should be sufficient to use (for example): ++ ++/amd/mp           amd.mp ++ ++in the master map and ++ ++automount: nis ++ ++in /etc/nsswitch.conf or ++ ++[ amd ] ++map_type = nis ++ ++in the configuration along with ++ ++[ /amd/mp ] ++ ++or ++ ++[ /amd/mp ] ++map_type = nis ++ ++ ++amd map options that can be used ++-------------------------------- ++ ++In an attempt to describe the usable amd map options, many of the amd ++map options have been added to autofs(5). ++ ++Not all the amd functionality has been implemented. The autofs(5) man ++page usually mentions if something hasn't been implemented so that's ++worth checking. ++ ++What hasn't been implemented ++---------------------------- ++ ++The configuration options fully_qualified_hosts, unmount_on_exit and ++browsable_dirs (and a couple of others) aren't implemented. ++ ++Map types (sources) ndbm, passwd are not implemented. ++The map source "sss" can't be used for amd format maps. ++ ++Map caching options aren't used, the existing autofs map caching is ++always used for available map sources. ++ ++The regex map key matching feature is not implemented. ++ ++Mount types lustre, nfsx, jfs, program and direct haven't been ++implemented and other mount types that aren't implemented in amd are ++also not available. ++ ++How to find out more ++-------------------- ++ ++Have a look at the man pages autofs.conf(5), autofs(5) and to a ++lesser extent auto.master(5). These may help. ++ ++But the best way to get more information is to ask on the ++autofs mailing list as described in the README file. ++ ++Ian diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-amd-config-descriptions-to-config.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-amd-config-descriptions-to-config.patch new file mode 100644 index 0000000..292c4a6 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-amd-config-descriptions-to-config.patch @@ -0,0 +1,458 @@ +autofs-5.0.9 - amd lookup add amd config descriptions to config + +From: Ian Kent + +Add amd configuration option descriptions to the default installed +configuration file. + +Including details about amd options that aren't used, haven't been +implemented or have different behaviour within autofs. +--- + redhat/autofs.conf.default.in | 214 ++++++++++++++++++++++++++++++++++++++++ + samples/autofs.conf.default.in | 214 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 428 insertions(+) + +diff --git a/redhat/autofs.conf.default.in b/redhat/autofs.conf.default.in +index c1362c7..ccccaab 100644 +--- a/redhat/autofs.conf.default.in ++++ b/redhat/autofs.conf.default.in +@@ -129,3 +129,217 @@ mount_nfs_default_protocol = 4 + # + #map_hash_table_size = 1024 + # ++# ++# Otions for the amd parser within autofs. ++# ++# amd configuration options that are aren't used, haven't been ++# implemented or have different behaviour within autofs. ++# ++# A number of the amd configuration options are not used by autofs, ++# some because they are not relevant within autofs, some because ++# they are done differently in autofs and others that are not yet ++# implemented. ++# ++# Since "mount_type" is always autofs (because there's no user space ++# NFS server) the configuration entries relating to that aren't used. ++# Also, server availability is done differently within autofs so the ++# options that relate to the amd server monitoring sub-system are ++# also not used. ++# ++# These options are mount_type, auto_attrcache, portmap_program, ++# nfs_vers_ping, nfs_allow_any_interface, nfs_allow_insecure_port, ++# nfs_proto, nfs_retransmit_counter, nfs_retransmit_counter_udp, ++# nfs_retransmit_counter_tcp, nfs_retransmit_counter_toplvl, ++# nfs_retry_interval, nfs_retry_interval_udp, nfs_retry_interval_tcp, ++# nfs_retry_interval_toplvl and nfs_vers. ++# ++# ++# Other options that are not used within the autofs implementation: ++# ++# log_file, truncate_log - autofs used either stderr when running in ++# the foreground or sends its output to syslog so an alternate ++# log file (or truncating the log) can't be used. ++# ++# print_pid - there's no corresponding option for this within autofs. ++# ++# use_tcpwrappers, show_statfs_entries - there's no user space NFS ++# server to control access to so this option isn't relevant. ++# The show_statfs_entries can't be implemented for the same ++# reason. ++# ++# debug_mtab_file - there's no user space NFS server and autofs ++# avoids using file based mtab whenever possible. ++# ++# sun_map_syntax - obviously, are provided by autofs itself. ++# ++# plock, show_statfs_entries, preferred_amq_port - not supported. ++# ++# ldap_cache_maxmem, ldap_cache_seconds - external ldap caching ++# is not used by autofs. ++# ++# ldap_proto_version - autofs always attempts to use the highest ++# available ldap protocol version. ++# ++# cache_duration, map_reload_interval, map_options - the map ++# entry cache is continually updated and stale entries ++# cleaned on re-load, which is done when map changes are ++# detected so these configuration entries are not used ++# by autofs. ++# ++# localhost_address - is not used within autofs. This ++# configuration option was only used in the amd user ++# space server code and is not relevant within autofs. ++# ++# ++# Options that are handled differently within autofs: ++# ++# pid_file - must be given as a command line option on startup. ++# ++# print_version - program version and feature information is obtained ++# by using the automount command line option "-V". ++# ++# debug_options, log_options - autofs has somewhat more limited ++# logging and debug logging options. When the log_options ++# options is encountered it is converted to the nearest ++# matching autofs logging option. Since the configuration ++# option debug_options would be handled the same way it ++# is ignored. ++# ++# restart_mounts - has no sensible meaning within autofs because autofs ++# always tries to re-connect to existing mounts. While this ++# has its own set of problems not re-connecting to existing ++# mounts always results in a non-functional automount tree if ++# mounts were busy at the last shutdown (as is also the case ++# with amd when using mount_type autofs). ++# ++# forced_unmounts - detaching mounts often causes serious problems ++# for users of existing mounts. It is used by autofs in some ++# cases, either at the explicit request of the user (with a ++# command line or init option) and in some special cases during ++# program operation but is avoided whenever possible. ++# ++# ++# A number of configuration options are not yet implemented: ++# ++# search_path - always a little frustrating, the compiled in ++# map location should be used to locate maps but isn't ++# in some cases. This requires work within autofs itself ++# and that will (obviously) include implementing this ++# configuration option for the amd map parser as well. ++# ++# fully_qualified_hosts - not yet implemented. ++# ++# unmount_on_exit - since autofs always tries to re-connect ++# to mounts left mounted from a previous shutdown this ++# is a sensible option to implement and that will be ++# done. ++# ++# browsable_dirs - not yet implemented. ++# ++# exec_map_timeout - a timeout is not currently used for ++# for program maps, might be implemented. ++# ++# tag - the tag option is not implemented within autofs. ++# ++# ++# Supported options: ++# ++# arch, karch, os, osver - these options default to what is returned ++# from uname(2) and can be overridden if required. ++# ++# full_os - has no default and must be set in the configuration ++# if used in maps. ++# ++# cluster - if not set defaults to the host domain name. This option ++# corresponds to the HP_UX cluster name (according to the amd ++# source) and is probably not used in Linux but is set anyway. ++# ++# vendor - has a default value of "unknown", it must be set in the ++# configuration if used in maps. ++# ++# auto_dir - is the base name of the mount tree used for external ++# mounts that are sometimes needed by amd maps. Its default ++# value is "/a". ++# ++# map_type - specifies the autofs map source, such as file, nis, ++# ldap etc. and has no default value set. ++# ++# map_defaults - is used to override /defaults entries within maps ++# and can be used to provide different defaults on specific ++# machines without having to modify centrally managed maps. ++# It is empty by default. ++# ++# dismount_interval - is equivalent to the autofs timeout option. It ++# is only possible to use this with type "auto" mounts due ++# to the way the autofs kernel module performs expiry. It ++# takes its default value from the autofs internal default ++# of 600 seconds. ++# ++# autofs_use_lofs - if set to "yes" autofs will attempt to use bind ++# mounts for type "auto" when possible. ++# ++# nis_domain - allows setting of a domain name other than the system ++# default. ++# ++# local_domain - is used to override (or set) the host domain name. ++# ++# normalize_hostnames - if set to "yes" then the contents of ${rhost} ++# is translated in its official host name. ++# ++# domain_strip - if set to "yes" the domain name part of the host ++# is strippped when normalizing hostnames. This can be useful ++# when using of the same maps in a multiple domain environment. ++# ++# normalize_slashes - is set to "yes" by default and will collapse ++# multiple unescaped occurrences of "/" to a single "/". ++# ++# selectors_in_defaults, selectors_on_default - has a default value ++# of "no". If set to "yes" then any defaults entry will be ++# checked for selectors to determine the values to be used. ++# selectors_in_defaults is the preferred option to use. ++# ++# ldap_base - has no default value. It must be set to the base dn ++# that is used for queries if ldap is to be used as a map ++# source. ++# ++# ldap_hostports - has no default value set. It must be set to ++# the URI of the LDAP server to be used for lookups when ++# ldap is used a map source. It may contain a comma or ++# space seperated list of LDAP URIs. ++# ++# hesiod_base - the base name used for hesiod map sources. ++# ++# Define global options for the amd parser within autofs. ++# ++[ amd ] ++# ++# Override the internal default with the same timeout that ++# is used by the override in the autofs configuration, sanity ++# only change. ++# ++dismount_interval = 300 ++# ++# map_type = file ++# ++# Overriding this can cause autofs to use less resources because ++# it will use symlinks instead of bind mounts in certain cases. ++# You should ensure that the autofs kernel module your using ++# supports expration of symlinks for best results (although this ++# appears to work reasonably well most of the time without the ++# update). ++# ++# autofs_use_lofs = no ++# ++# Several configuration options can be set per mount point. ++# In particulr map_type, map_name, map_defaults, search_path, ++# browsable_dirs, dismount_interval and selectors_in_defaults ++# (not all of which are currently implemented, see above). ++# ++# Also, if a section for an amd mount point is defined here ++# it isn't necessary to specify the format in the corresponding ++# master map entry and the format will be inherited for type ++# "auto" mounts. ++# ++# [ /expamle/mount ] ++# dismount_interval = 60 ++# map_type = nis +diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in +index c8e4006..616bc66 100644 +--- a/samples/autofs.conf.default.in ++++ b/samples/autofs.conf.default.in +@@ -128,3 +128,217 @@ browse_mode = no + # + #map_hash_table_size = 1024 + # ++# ++# Otions for the amd parser within autofs. ++# ++# amd configuration options that are aren't used, haven't been ++# implemented or have different behaviour within autofs. ++# ++# A number of the amd configuration options are not used by autofs, ++# some because they are not relevant within autofs, some because ++# they are done differently in autofs and others that are not yet ++# implemented. ++# ++# Since "mount_type" is always autofs (because there's no user space ++# NFS server) the configuration entries relating to that aren't used. ++# Also, server availability is done differently within autofs so the ++# options that relate to the amd server monitoring sub-system are ++# also not used. ++# ++# These options are mount_type, auto_attrcache, portmap_program, ++# nfs_vers_ping, nfs_allow_any_interface, nfs_allow_insecure_port, ++# nfs_proto, nfs_retransmit_counter, nfs_retransmit_counter_udp, ++# nfs_retransmit_counter_tcp, nfs_retransmit_counter_toplvl, ++# nfs_retry_interval, nfs_retry_interval_udp, nfs_retry_interval_tcp, ++# nfs_retry_interval_toplvl and nfs_vers. ++# ++# ++# Other options that are not used within the autofs implementation: ++# ++# log_file, truncate_log - autofs used either stderr when running in ++# the foreground or sends its output to syslog so an alternate ++# log file (or truncating the log) can't be used. ++# ++# print_pid - there's no corresponding option for this within autofs. ++# ++# use_tcpwrappers, show_statfs_entries - there's no user space NFS ++# server to control access to so this option isn't relevant. ++# The show_statfs_entries can't be implemented for the same ++# reason. ++# ++# debug_mtab_file - there's no user space NFS server and autofs ++# avoids using file based mtab whenever possible. ++# ++# sun_map_syntax - obviously, are provided by autofs itself. ++# ++# plock, show_statfs_entries, preferred_amq_port - not supported. ++# ++# ldap_cache_maxmem, ldap_cache_seconds - external ldap caching ++# is not used by autofs. ++# ++# ldap_proto_version - autofs always attempts to use the highest ++# available ldap protocol version. ++# ++# cache_duration, map_reload_interval, map_options - the map ++# entry cache is continually updated and stale entries ++# cleaned on re-load, which is done when map changes are ++# detected so these configuration entries are not used ++# by autofs. ++# ++# localhost_address - is not used within autofs. This ++# configuration option was only used in the amd user ++# space server code and is not relevant within autofs. ++# ++# ++# Options that are handled differently within autofs: ++# ++# pid_file - must be given as a command line option on startup. ++# ++# print_version - program version and feature information is obtained ++# by using the automount command line option "-V". ++# ++# debug_options, log_options - autofs has somewhat more limited ++# logging and debug logging options. When the log_options ++# options is encountered it is converted to the nearest ++# matching autofs logging option. Since the configuration ++# option debug_options would be handled the same way it ++# is ignored. ++# ++# restart_mounts - has no sensible meaning within autofs because autofs ++# always tries to re-connect to existing mounts. While this ++# has its own set of problems not re-connecting to existing ++# mounts always results in a non-functional automount tree if ++# mounts were busy at the last shutdown (as is also the case ++# with amd when using mount_type autofs). ++# ++# forced_unmounts - detaching mounts often causes serious problems ++# for users of existing mounts. It is used by autofs in some ++# cases, either at the explicit request of the user (with a ++# command line or init option) and in some special cases during ++# program operation but is avoided whenever possible. ++# ++# ++# A number of configuration options are not yet implemented: ++# ++# search_path - always a little frustrating, the compiled in ++# map location should be used to locate maps but isn't ++# in some cases. This requires work within autofs itself ++# and that will (obviously) include implementing this ++# configuration option for the amd map parser as well. ++# ++# fully_qualified_hosts - not yet implemented. ++# ++# unmount_on_exit - since autofs always tries to re-connect ++# to mounts left mounted from a previous shutdown this ++# is a sensible option to implement and that will be ++# done. ++# ++# browsable_dirs - not yet implemented. ++# ++# exec_map_timeout - a timeout is not currently used for ++# for program maps, might be implemented. ++# ++# tag - the tag option is not implemented within autofs. ++# ++# ++# Supported options: ++# ++# arch, karch, os, osver - these options default to what is returned ++# from uname(2) and can be overridden if required. ++# ++# full_os - has no default and must be set in the configuration ++# if used in maps. ++# ++# cluster - if not set defaults to the host domain name. This option ++# corresponds to the HP_UX cluster name (according to the amd ++# source) and is probably not used in Linux but is set anyway. ++# ++# vendor - has a default value of "unknown", it must be set in the ++# configuration if used in maps. ++# ++# auto_dir - is the base name of the mount tree used for external ++# mounts that are sometimes needed by amd maps. Its default ++# value is "/a". ++# ++# map_type - specifies the autofs map source, such as file, nis, ++# ldap etc. and has no default value set. ++# ++# map_defaults - is used to override /defaults entries within maps ++# and can be used to provide different defaults on specific ++# machines without having to modify centrally managed maps. ++# It is empty by default. ++# ++# dismount_interval - is equivalent to the autofs timeout option. It ++# is only possible to use this with type "auto" mounts due ++# to the way the autofs kernel module performs expiry. It ++# takes its default value from the autofs internal default ++# of 600 seconds. ++# ++# autofs_use_lofs - if set to "yes" autofs will attempt to use bind ++# mounts for type "auto" when possible. ++# ++# nis_domain - allows setting of a domain name other than the system ++# default. ++# ++# local_domain - is used to override (or set) the host domain name. ++# ++# normalize_hostnames - if set to "yes" then the contents of ${rhost} ++# is translated in its official host name. ++# ++# domain_strip - if set to "yes" the domain name part of the host ++# is strippped when normalizing hostnames. This can be useful ++# when using of the same maps in a multiple domain environment. ++# ++# normalize_slashes - is set to "yes" by default and will collapse ++# multiple unescaped occurrences of "/" to a single "/". ++# ++# selectors_in_defaults, selectors_on_default - has a default value ++# of "no". If set to "yes" then any defaults entry will be ++# checked for selectors to determine the values to be used. ++# selectors_in_defaults is the preferred option to use. ++# ++# ldap_base - has no default value. It must be set to the base dn ++# that is used for queries if ldap is to be used as a map ++# source. ++# ++# ldap_hostports - has no default value set. It must be set to ++# the URI of the LDAP server to be used for lookups when ++# ldap is used a map source. It may contain a comma or ++# space seperated list of LDAP URIs. ++# ++# hesiod_base - the base name used for hesiod map sources. ++# ++# Define global options for the amd parser within autofs. ++# ++[ amd ] ++# ++# Override the internal default with the same timeout that ++# is used by the override in the autofs configuration, sanity ++# only change. ++# ++dismount_interval = 300 ++# ++# map_type = file ++# ++# Overriding this can cause autofs to use less resources because ++# it will use symlinks instead of bind mounts in certain cases. ++# You should ensure that the autofs kernel module your using ++# supports expration of symlinks for best results (although this ++# appears to work reasonably well most of the time without the ++# update). ++# ++# autofs_use_lofs = no ++# ++# Several configuration options can be set per mount point. ++# In particulr map_type, map_name, map_defaults, search_path, ++# browsable_dirs, dismount_interval and selectors_in_defaults ++# (not all of which are currently implemented, see above). ++# ++# Also, if a section for an amd mount point is defined here ++# it isn't necessary to specify the format in the corresponding ++# master map entry and the format will be inherited for type ++# "auto" mounts. ++# ++# [ /expamle/mount ] ++# dismount_interval = 60 ++# map_type = nis diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-amd-global-macro-vars.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-amd-global-macro-vars.patch new file mode 100644 index 0000000..a1d8884 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-amd-global-macro-vars.patch @@ -0,0 +1,218 @@ +autofs-5.0.9 - amd lookup add amd global macro vars + +From: Ian Kent + + +--- + include/mounts.h | 2 + + lib/macros.c | 60 +++++++++++++++++++++++++++++++++++++++++- + lib/mounts.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 137 insertions(+), 2 deletions(-) + +diff --git a/include/mounts.h b/include/mounts.h +index 3bef086..ca99f8b 100644 +--- a/include/mounts.h ++++ b/include/mounts.h +@@ -87,6 +87,8 @@ extern unsigned int nfs_mount_uses_string_options; + + struct substvar *addstdenv(struct substvar *sv); + struct substvar *removestdenv(struct substvar *sv); ++void add_std_amd_vars(struct substvar *sv); ++void remove_std_amd_vars(void); + + unsigned int query_kproto_ver(void); + unsigned int get_kver_major(void); +diff --git a/lib/macros.c b/lib/macros.c +index 5109abc..ff9ba89 100644 +--- a/lib/macros.c ++++ b/lib/macros.c +@@ -18,11 +18,17 @@ + #include + #include + #include ++#include + + #include "automount.h" + + static struct utsname un; + static char processor[65]; /* Not defined on Linux, so we make our own */ ++static char hostname[HOST_NAME_MAX + 1]; ++static char host[HOST_NAME_MAX]; ++static char domain[HOST_NAME_MAX]; ++static char hostd[HOST_NAME_MAX + 1]; ++static char endian[] = "unknown"; + + /* Predefined variables: tail of link chain */ + static struct substvar +@@ -31,10 +37,18 @@ static struct substvar + sv_host = {"HOST", un.nodename, 1, &sv_cpu}, + sv_osname = {"OSNAME", un.sysname, 1, &sv_host}, + sv_osrel = {"OSREL", un.release, 1, &sv_osname}, +- sv_osvers = {"OSVERS", un.version, 1, &sv_osrel ++ sv_osvers = {"OSVERS", un.version, 1, &sv_osrel}, ++ sv_dollar = {"dollar", "$", 1, &sv_osvers}, ++ sv_true = {"true", "1", 1, &sv_dollar}, ++ sv_false = {"false", "0", 1, &sv_true}, ++ sv_byte = {"byte", endian, 1, &sv_false}, ++ sv_host2 = {"host", host, 1, &sv_byte}, ++ sv_xhost = {"xhost", host, 1, &sv_host2}, ++ sv_domain = {"domain", domain, 1, &sv_xhost}, ++ sv_hostd = {"hostd", hostd, 1, &sv_domain + }; + +-static struct substvar *system_table = &sv_osvers; ++static struct substvar *system_table = &sv_hostd; + static unsigned int macro_init_done = 0; + + static pthread_mutex_t table_mutex = PTHREAD_MUTEX_INITIALIZER; +@@ -63,6 +77,13 @@ void dump_table(struct substvar *table) + /* Get processor information for predefined macro definitions */ + void macro_init(void) + { ++ char *local_domain; ++ ++ memset(hostname, 0, HOST_NAME_MAX + 1); ++ memset(host, 0, HOST_NAME_MAX); ++ memset(domain, 0, HOST_NAME_MAX); ++ memset(hostd, 0, HOST_NAME_MAX + 1); ++ + macro_lock(); + if (macro_init_done) { + macro_unlock(); +@@ -79,6 +100,41 @@ void macro_init(void) + !strcmp(processor + 2, "86")) + processor[1] = '3'; + ++ local_domain = conf_amd_get_sub_domain(); ++ ++ if (!gethostname(hostname, HOST_NAME_MAX)) { ++ char *dot; ++ dot = strchr(hostname, '.'); ++ if (dot) { ++ *dot++ = '\0'; ++ strcpy(domain, dot); ++ } ++ strcpy(host, hostname); ++ strcpy(hostd, host); ++ if (*domain || local_domain) { ++ strcat(hostd, "."); ++ if (!local_domain) ++ strcat(hostd, domain); ++ else { ++ strcat(hostd, local_domain); ++ strcpy(domain, local_domain); ++ } ++ } ++ } ++ ++ if (sizeof(short) == 2) { ++ union { short s; char c[sizeof(short)]; } order; ++ order.s = 0x0102; ++ if (order.c[0] == 1 && order.c[1] == 2) ++ strcpy(endian, "big"); ++ else if (order.c[0] == 2 && order.c[1] == 1) ++ strcpy(endian, "little"); ++ else ++ strcpy(endian, "unknown"); ++ } ++ ++ add_std_amd_vars(system_table); ++ + macro_init_done = 1; + macro_unlock(); + return; +diff --git a/lib/mounts.c b/lib/mounts.c +index aea6691..4306974 100644 +--- a/lib/mounts.c ++++ b/lib/mounts.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include "automount.h" + +@@ -365,6 +366,82 @@ struct substvar *removestdenv(struct substvar *sv) + return list; + } + ++void add_std_amd_vars(struct substvar *sv) ++{ ++ char *tmp; ++ ++ tmp = conf_amd_get_arch(); ++ if (tmp) { ++ macro_global_addvar("arch", 4, tmp); ++ free(tmp); ++ } ++ ++ tmp = conf_amd_get_karch(); ++ if (tmp) { ++ macro_global_addvar("karch", 5, tmp); ++ free(tmp); ++ } ++ ++ tmp = conf_amd_get_os(); ++ if (tmp) { ++ macro_global_addvar("os", 2, tmp); ++ free(tmp); ++ } ++ ++ tmp = conf_amd_get_full_os(); ++ if (tmp) { ++ macro_global_addvar("full_os", 7, tmp); ++ free(tmp); ++ } ++ ++ tmp = conf_amd_get_os_ver(); ++ if (tmp) { ++ macro_global_addvar("osver", 5, tmp); ++ free(tmp); ++ } ++ ++ tmp = conf_amd_get_vendor(); ++ if (tmp) { ++ macro_global_addvar("vendor", 6, tmp); ++ free(tmp); ++ } ++ ++ /* Umm ... HP_UX cluster name, probably not used */ ++ tmp = conf_amd_get_cluster(); ++ if (tmp) { ++ macro_global_addvar("cluster", 7, tmp); ++ free(tmp); ++ } else { ++ const struct substvar *v = macro_findvar(sv, "domain", 4); ++ if (v && *v->val) { ++ tmp = strdup(v->val); ++ if (tmp) ++ macro_global_addvar("cluster", 7, tmp); ++ } ++ } ++ ++ tmp = conf_amd_get_auto_dir(); ++ if (tmp) { ++ macro_global_addvar("autodir", 7, tmp); ++ free(tmp); ++ } ++ ++ return; ++} ++ ++void remove_std_amd_vars(void) ++{ ++ macro_global_removevar("autodir", 7); ++ macro_global_removevar("cluster", 7); ++ macro_global_removevar("vendor", 6); ++ macro_global_removevar("osver", 5); ++ macro_global_removevar("full_os", 7); ++ macro_global_removevar("os", 2); ++ macro_global_removevar("karch", 5); ++ macro_global_removevar("arch", 4); ++ return; ++ } ++ + /* + * Make common autofs mount options string + */ diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-cache-partial-match-functions.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-cache-partial-match-functions.patch new file mode 100644 index 0000000..29df044 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-cache-partial-match-functions.patch @@ -0,0 +1,92 @@ +autofs-5.0.9 - amd lookup add cache partial match functions + +From: Ian Kent + +Partial key matching is used for amd. A prefix is possibly added to the key +and if the map entry key has a trailing /* and matches the initial part of +the key+prefix the match succeeds. + +Update the existing partial match functions to help with this. +--- + include/automount.h | 1 + + lib/cache.c | 38 +++++++++++++++++++++++++++++++++----- + 2 files changed, 34 insertions(+), 5 deletions(-) + +diff --git a/include/automount.h b/include/automount.h +index 37133fe..ac6c4e3 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -215,6 +215,7 @@ struct mapent *cache_lookup(struct mapent_cache *mc, const char *key); + struct mapent *cache_lookup_distinct(struct mapent_cache *mc, const char *key); + struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int start, struct list_head *head); + struct mapent *cache_partial_match(struct mapent_cache *mc, const char *prefix); ++struct mapent *cache_partial_match_wild(struct mapent_cache *mc, const char *prefix); + int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age); + int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age); + void cache_update_negative(struct mapent_cache *mc, struct map_source *ms, const char *key, time_t timeout); +diff --git a/lib/cache.c b/lib/cache.c +index 9af1709..8d08094 100644 +--- a/lib/cache.c ++++ b/lib/cache.c +@@ -566,7 +566,9 @@ struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int s + } + + /* cache must be read locked by caller */ +-struct mapent *cache_partial_match(struct mapent_cache *mc, const char *prefix) ++static struct mapent *__cache_partial_match(struct mapent_cache *mc, ++ const char *prefix, ++ unsigned int type) + { + struct mapent *me = NULL; + size_t len = strlen(prefix); +@@ -578,20 +580,46 @@ struct mapent *cache_partial_match(struct mapent_cache *mc, const char *prefix) + continue; + + if (len < strlen(me->key) && +- (strncmp(prefix, me->key, len) == 0) && me->key[len] == '/') +- return me; ++ (strncmp(prefix, me->key, len) == 0) && ++ me->key[len] == '/') { ++ if (type == LKP_NORMAL) ++ return me; ++ if (type == LKP_WILD && ++ me->key[len] != '\0' && ++ me->key[len + 1] == '*') ++ return me; ++ } + + me = me->next; + while (me != NULL) { + if (len < strlen(me->key) && +- strncmp(prefix, me->key, len) == 0 && me->key[len] == '/') +- return me; ++ (strncmp(prefix, me->key, len) == 0 && ++ me->key[len] == '/')) { ++ if (type == LKP_NORMAL) ++ return me; ++ if (type == LKP_WILD && ++ me->key[len] != '\0' && ++ me->key[len + 1] == '*') ++ return me; ++ } + me = me->next; + } + } + return NULL; + } + ++/* cache must be read locked by caller */ ++struct mapent *cache_partial_match(struct mapent_cache *mc, const char *prefix) ++{ ++ return __cache_partial_match(mc, prefix, LKP_NORMAL); ++} ++ ++/* cache must be read locked by caller */ ++struct mapent *cache_partial_match_wild(struct mapent_cache *mc, const char *prefix) ++{ ++ return __cache_partial_match(mc, prefix, LKP_WILD); ++} ++ + /* cache must be write locked by caller */ + int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age) + { diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-cdfs-fs-type.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-cdfs-fs-type.patch new file mode 100644 index 0000000..68a8187 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-cdfs-fs-type.patch @@ -0,0 +1,63 @@ +autofs-5.0.8 - amd lookup add cdfs fs type + +From: Ian Kent + + +--- + include/parse_amd.h | 1 + + modules/amd_parse.y | 3 +++ + modules/amd_tok.l | 2 +- + modules/parse_amd.c | 1 + + 4 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/include/parse_amd.h b/include/parse_amd.h +index 4015e9f..401aadb 100644 +--- a/include/parse_amd.h ++++ b/include/parse_amd.h +@@ -28,6 +28,7 @@ + #define AMD_MOUNT_TYPE_XFS 0x00000200 + #define AMD_MOUNT_TYPE_JFS 0x00000400 + #define AMD_MOUNT_TYPE_CACHEFS 0x00000800 ++#define AMD_MOUNT_TYPE_CDFS 0x00001000 + #define AMD_MOUNT_TYPE_MASK 0x0000ffff + + #define AMD_ENTRY_CUT 0x00010000 +diff --git a/modules/amd_parse.y b/modules/amd_parse.y +index 1d4a0a3..87e3309 100644 +--- a/modules/amd_parse.y ++++ b/modules/amd_parse.y +@@ -269,6 +269,9 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE + !strcmp($3, "ext4")) { + entry.flags |= AMD_MOUNT_TYPE_EXT; + entry.type = amd_strdup($3); ++ } else if (!strcmp($3, "cdfs")) { ++ entry.flags |= AMD_MOUNT_TYPE_CDFS; ++ entry.type = amd_strdup("iso9660"); + } else if (!strcmp($3, "jfs") || + !strcmp($3, "nfsx") || + !strcmp($3, "program") || +diff --git a/modules/amd_tok.l b/modules/amd_tok.l +index 8a6d40c..10b1963 100644 +--- a/modules/amd_tok.l ++++ b/modules/amd_tok.l +@@ -99,7 +99,7 @@ MNTOPT (opts|addopts|remopts) + FSOPTS (rhost|rfs|dev|cachedir|mount|unmount|umount|delay) + CHEOPT (mapdefault|none|inc|re|regexp|all) + MAPTYPE (file|nis|nisplus|ldap|hesiod|exec|ndbm|passwd|union) +-FSTYPE_LOCAL (link|linkx|lofs|ext2|ext3|ext4|xfs|jfs|cachefs) ++FSTYPE_LOCAL (link|linkx|lofs|ext2|ext3|ext4|xfs|jfs|cdfs|cachefs) + FSTYPE_NET (nfs|nfsx|nfsl|host) + FSTYPE (auto|program|direct|lustre|{FSTYPE_LOCAL}|{FSTYPE_NET}) + +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index bc53b1d..fa0f75d 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -1286,6 +1286,7 @@ static int amd_mount(struct autofs_point *ap, const char *name, + + case AMD_MOUNT_TYPE_EXT: + case AMD_MOUNT_TYPE_XFS: ++ case AMD_MOUNT_TYPE_CDFS: + if (!validate_generic_options(ap->logopt, fstype, entry)) + return 1; + ret = do_generic_mount(ap, name, entry, entry->dev, flags); diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-conf-handling-for-amd-maps.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-conf-handling-for-amd-maps.patch new file mode 100644 index 0000000..413cfeb --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-conf-handling-for-amd-maps.patch @@ -0,0 +1,1063 @@ +autofs-5.0.9 - amd lookup add conf handling for amd maps + +From: Ian Kent + + +--- + include/defaults.h | 111 ++++++++ + lib/defaults.c | 753 ++++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 811 insertions(+), 53 deletions(-) + +diff --git a/include/defaults.h b/include/defaults.h +index 3bfcd49..033acaf 100644 +--- a/include/defaults.h ++++ b/include/defaults.h +@@ -46,6 +46,91 @@ + + #define DEFAULT_MAP_HASH_TABLE_SIZE "1024" + ++/* Config entry flags */ ++#define CONF_NONE 0x00000000 ++#define CONF_ENV 0x00000001 ++#define CONF_NOTUSED 0x00000002 ++#define CONF_NOTSUP 0x00000004 ++#define CONF_BROWSABLE_DIRS 0x00000008 ++#define CONF_MOUNT_TYPE_AUTOFS 0x00000010 ++#define CONF_SELECTORS_IN_DEFAULTS 0x00000020 ++#define CONF_NORMALIZE_HOSTNAMES 0x00000040 ++#define CONF_PROCESS_LOCK 0x00000080 ++#define CONF_RESTART_EXISTING_MOUNTS 0x00000100 ++#define CONF_SHOW_STATFS_ENTRIES 0x00000200 ++#define CONF_FULLY_QUALIFIED_HOSTS 0x00000400 ++#define CONF_UNMOUNT_ON_EXIT 0x00000800 ++#define CONF_AUTOFS_USE_LOFS 0x00001000 ++#define CONF_DOMAIN_STRIP 0x00002000 ++#define CONF_NORMALIZE_SLASHES 0x00004000 ++#define CONF_FORCED_UNMOUNTS 0x00008000 ++ ++#define DEFAULT_AMD_NULL_VALUE NULL ++ ++#define DEFAULT_AMD_AUTO_ATTRCACHE DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_AUTO_DIR "/a" ++#define DEFAULT_AMD_AUTOFS_USE_LOFS "yes" ++#define DEFAULT_AMD_BROWSABLE_DIRS "no" ++#define DEFAULT_AMD_CACHE_DURATION "300" ++#define DEFAULT_AMD_CLUSTER DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_DEBUG_MTAB_FILE DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_DEBUG_OPTIONS DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_DISMOUNT_INTERVAL DEFAULT_TIMEOUT ++#define DEFAULT_AMD_DOMAIN_STRIP "yes" ++#define DEFAULT_AMD_EXEC_MAP_TIMEOUT "10" ++#define DEFAULT_AMD_FORCED_UMOUNTS "no" ++#define DEFAULT_AMD_FULLY_QUALIFIED_HOSTS "no" ++#define DEFAULT_AMD_FULL_OS DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_HESIOD_BASE "automount" ++#define DEFAULT_AMD_KARCH DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_LDAP_BASE DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_LDAP_CACHE_MAXMEM "131072" ++#define DEFAULT_AMD_LDAP_CACHE_SECONDS "0" ++#define DEFAULT_AMD_LDAP_HOSTPORTS DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_LDAP_PROTO_VERSION "2" ++#define DEFAULT_AMD_SUB_DOMAIN DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_LOCALHOST_ADDRESS "localhost" ++#define DEFAULT_AMD_LOG_FILE DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_LOG_OPTIONS "defaults" ++#define DEFAULT_AMD_MAP_DEFAULTS DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_MAP_OPTIONS DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_MAP_RELOAD_INTERVAL "3600" ++#define DEFAULT_AMD_MAP_TYPE DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_MOUNT_TYPE "autofs" ++#define DEFAULT_AMD_PID_FILE DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_PORTMAP_PROGRAM DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_PREFERRED_AMQ_PORT DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_ALLOW_ANY_INTERFACE DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_ALLOW_INSECURE_PORT DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_PROTO DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_RETRANSMIT_COUNTER DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_RETRANSMIT_COUNTER_UDP DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_RETRANSMIT_COUNTER_TCP DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_RETRANSMIT_COUNTER_TOPLVL DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_RETRY_INTERVAL DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_RETRY_INTERVAL_UDP DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_RETRY_INTERVAL_TCP DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_RETRY_INTERVAL_TOPLVL DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_VERS DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NFS_VERS_PING DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NIS_DOMAIN DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_NORMALIZE_HOSTNAMES "no" ++#define DEFAULT_AMD_NORMALIZE_SLASHES "yes" ++#define DEFAULT_AMD_OS DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_OSVER DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_PLOCK "yes" ++#define DEFAULT_AMD_PRINT_PID DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_PRINT_VERSION DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_RESTART_MOUNTS "no" ++#define DEFAULT_AMD_SEARCH_PATH DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_SELECTORS_IN_DEFAULTS "no" ++#define DEFAULT_AMD_SHOW_STATFS_ENTRIES DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_SUN_MAP_SYNTAX DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_TRUNCATE_LOG DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_UMOUNT_ON_EXIT "yes" ++#define DEFAULT_AMD_USE_TCPWRAPPERS DEFAULT_AMD_NULL_VALUE ++#define DEFAULT_AMD_VENDOR "unknown" ++ + #ifdef WITH_LDAP + struct ldap_schema; + struct ldap_searchdn; +@@ -75,5 +160,31 @@ unsigned int defaults_get_umount_wait(void); + const char *defaults_get_auth_conf_file(void); + unsigned int defaults_get_map_hash_table_size(void); + ++unsigned int conf_amd_mount_section_exists(const char *); ++char *conf_amd_get_arch(void); ++char *conf_amd_get_karch(void); ++char *conf_amd_get_os(void); ++char *conf_amd_get_os_ver(void); ++char *conf_amd_get_vendor(void); ++char *conf_amd_get_full_os(void); ++char *conf_amd_get_auto_dir(void); ++char *conf_amd_get_cluster(void); ++unsigned int conf_amd_get_exec_map_timeout(void); ++char *conf_amd_get_hesiod_base(void); ++char *conf_amd_get_karch(void); ++char *conf_amd_get_ldap_base(void); ++char *conf_amd_get_ldap_hostports(void); ++char *conf_amd_get_sub_domain(void); ++char *conf_amd_get_localhost_address(void); ++unsigned int conf_amd_get_log_options(void); ++char *conf_amd_get_nfs_proto(void); ++char *conf_amd_get_nis_domain(void); ++unsigned int conf_amd_set_nis_domain(const char *); ++char *conf_amd_get_map_defaults(const char *); ++char *conf_amd_get_map_type(const char *); ++char *conf_amd_get_search_path(const char *); ++unsigned int conf_amd_get_dismount_interval(const char *); ++unsigned long conf_amd_get_flags(const char *); ++ + #endif + +diff --git a/lib/defaults.c b/lib/defaults.c +index 29f3f00..bb304f3 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + + #include "config.h" +@@ -30,9 +31,11 @@ + #include "automount.h" + + #define AUTOFS_GLOBAL_SECTION "autofs" ++#define AMD_GLOBAL_SECTION "amd" + + #define DEFAULT_CONFIG_FILE AUTOFS_CONF_DIR "/autofs" + #define MAX_LINE_LEN 256 ++#define MAX_SECTION_NAME MAX_LINE_LEN + + #define NAME_MASTER_MAP "master_map_name" + +@@ -61,20 +64,84 @@ + + #define NAME_MAP_HASH_TABLE_SIZE "map_hash_table_size" + ++#define NAME_AMD_ARCH "arch" ++#define NAME_AMD_AUTO_ATTRCACHE "auto_attrcache" ++#define NAME_AMD_AUTO_DIR "auto_dir" ++#define NAME_AMD_AUTOFS_USE_LOFS "autofs_use_lofs" ++#define NAME_AMD_BROWSABLE_DIRS "browsable_dirs" ++#define NAME_AMD_CACHE_DURATION "cache_duration" ++#define NAME_AMD_CLUSTER "cluster" ++#define NAME_AMD_DEBUG_MTAB_FILE "debug_mtab_file" ++#define NAME_AMD_DEBUG_OPTIONS "debug_options" ++#define NAME_AMD_DISMOUNT_INTERVAL "dismount_interval" ++#define NAME_AMD_DOMAIN_STRIP "domain_strip" ++#define NAME_AMD_EXEC_MAP_TIMEOUT "exec_map_timeout" ++#define NAME_AMD_FORCED_UMOUNTS "forced_unmounts" ++#define NAME_AMD_FULLY_QUALIFIED_HOSTS "fully_qualified_hosts" ++#define NAME_AMD_FULL_OS "full_os" ++#define NAME_AMD_HESIOD_BASE "hesiod_base" ++#define NAME_AMD_KARCH "karch" ++#define NAME_AMD_LDAP_BASE "ldap_base" ++#define NAME_AMD_LDAP_CACHE_MAXMEM "ldap_cache_maxmem" ++#define NAME_AMD_LDAP_CACHE_SECONDS "ldap_cache_seconds" ++#define NAME_AMD_LDAP_HOSTPORTS "ldap_hostports" ++#define NAME_AMD_LDAP_PROTO_VERSION "ldap_proto_version" ++#define NAME_AMD_SUB_DOMAIN "local_domain" ++#define NAME_AMD_LOCALHOST_ADDRESS "localhost_address" ++#define NAME_AMD_LOG_FILE "log_file" ++#define NAME_AMD_LOG_OPTIONS "log_options" ++#define NAME_AMD_MAP_DEFAULTS "map_defaults" ++#define NAME_AMD_MAP_OPTIONS "map_options" ++#define NAME_AMD_MAP_RELOAD_INTERVAL "map_reload_interval" ++#define NAME_AMD_MAP_TYPE "map_type" ++#define NAME_AMD_MOUNT_TYPE "mount_type" ++#define NAME_AMD_PID_FILE "pid_file" ++#define NAME_AMD_PORTMAP_PROGRAM "portmap_program" ++#define NAME_AMD_PREFERRED_AMQ_PORT "preferred_amq_port" ++#define NAME_AMD_NFS_ALLOW_ANY_INTERFACE "nfs_allow_any_interface" ++#define NAME_AMD_NFS_ALLOW_INSECURE_PORT "nfs_allow_insecure_port" ++#define NAME_AMD_NFS_PROTO "nfs_proto" ++#define NAME_AMD_NFS_RETRANSMIT_COUNTER "nfs_retransmit_counter" ++#define NAME_AMD_NFS_RETRANSMIT_COUNTER_UDP "nfs_retransmit_counter_udp" ++#define NAME_AMD_NFS_RETRANSMIT_COUNTER_TCP "nfs_retransmit_counter_tcp" ++#define NAME_AMD_NFS_RETRANSMIT_COUNTER_TOPLVL "nfs_retransmit_counter_toplvl" ++#define NAME_AMD_NFS_RETRY_INTERVAL "nfs_retry_interval" ++#define NAME_AMD_NFS_RETRY_INTERVAL_UDP "nfs_retry_interval_udp" ++#define NAME_AMD_NFS_RETRY_INTERVAL_TCP "nfs_retry_interval_tcp" ++#define NAME_AMD_NFS_RETRY_INTERVAL_TOPLVL "nfs_retry_interval_toplvl" ++#define NAME_AMD_NFS_VERS "nfs_vers" ++#define NAME_AMD_NFS_VERS_PING "nfs_vers_ping" ++#define NAME_AMD_NIS_DOMAIN "nis_domain" ++#define NAME_AMD_NORMALIZE_HOSTNAMES "normalize_hostnames" ++#define NAME_AMD_NORMALIZE_SLASHES "normalize_slashes" ++#define NAME_AMD_OS "os" ++#define NAME_AMD_OSVER "osver" ++#define NAME_AMD_PLOCK "plock" ++#define NAME_AMD_PRINT_PID "print_pid" ++#define NAME_AMD_PRINT_VERSION "print_version" ++#define NAME_AMD_RESTART_MOUNTS "restart_mounts" ++#define NAME_AMD_SEARCH_PATH "search_path" ++#define NAME_AMD_SELECTORS_ON_DEFAULT "selectors_on_default" ++#define NAME_AMD_SELECTORS_IN_DEFAULTS "selectors_in_defaults" ++#define NAME_AMD_SHOW_STATFS_ENTRIES "show_statfs_entries" ++#define NAME_AMD_SUN_MAP_SYNTAX "sun_map_syntax" ++#define NAME_AMD_TRUNCATE_LOG "truncate_log" ++#define NAME_AMD_UMOUNT_ON_EXIT "unmount_on_exit" ++#define NAME_AMD_USE_TCPWRAPPERS "use_tcpwrappers" ++#define NAME_AMD_VENDOR "vendor" ++ + /* Status returns */ + #define CFG_OK 0x0000 + #define CFG_FAIL 0x0001 + #define CFG_EXISTS 0x0002 + #define CFG_NOTFOUND 0x0004 + +-/* Config entry flags */ +-#define CONF_ENV 0x00000001 +- + #define CFG_TABLE_SIZE 128 + + static const char *default_master_map_name = DEFAULT_MASTER_MAP_NAME; + static const char *default_auth_conf_file = DEFAULT_AUTH_CONF_FILE; + static const char *autofs_gbl_sec = AUTOFS_GLOBAL_SECTION; ++static const char *amd_gbl_sec = AMD_GLOBAL_SECTION; + + struct conf_option { + char *section; +@@ -288,30 +355,211 @@ error: + return 0; + } + ++static int conf_load_amd_defaults(void) ++{ ++ struct utsname uts; ++ const char *sec = amd_gbl_sec; ++ char *host_os_name, *host_os_version, *host_arch; ++ int ret; ++ ++ if (uname(&uts)) { ++ host_os_name = uts.sysname; ++ host_os_version = uts.release; ++ host_arch = uts.machine; ++ } else { ++ host_os_name = NULL; ++ host_os_version = NULL; ++ host_arch = NULL; ++ } ++ ++ ret = conf_update(sec, NAME_AMD_ARCH, host_arch, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_KARCH, host_arch, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_OS, host_os_name, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_OSVER, host_os_version, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_AUTO_DIR, ++ DEFAULT_AMD_AUTO_DIR, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_AUTOFS_USE_LOFS, ++ DEFAULT_AMD_AUTO_DIR, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_BROWSABLE_DIRS, ++ DEFAULT_AMD_BROWSABLE_DIRS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_CLUSTER, ++ DEFAULT_AMD_CLUSTER, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ /* ++ * DISMOUNT_INTERVAL defers to the autofs default so we ++ * don't set an amd default in the configuration. ++ */ ++ /*ret = conf_update(sec, NAME_AMD_DISMOUNT_INTERVAL, ++ DEFAULT_AMD_DISMOUNT_INTERVAL, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error;*/ ++ ++ ret = conf_update(sec, NAME_AMD_DOMAIN_STRIP, ++ DEFAULT_AMD_DOMAIN_STRIP, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_EXEC_MAP_TIMEOUT, ++ DEFAULT_AMD_EXEC_MAP_TIMEOUT, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_FORCED_UMOUNTS, ++ DEFAULT_AMD_FORCED_UMOUNTS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_FULLY_QUALIFIED_HOSTS, ++ DEFAULT_AMD_FULLY_QUALIFIED_HOSTS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_FULL_OS, ++ DEFAULT_AMD_FULL_OS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_HESIOD_BASE, ++ DEFAULT_AMD_HESIOD_BASE, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_KARCH, host_arch, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_LDAP_BASE, ++ DEFAULT_AMD_LDAP_BASE, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_LDAP_HOSTPORTS, ++ DEFAULT_AMD_LDAP_HOSTPORTS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_SUB_DOMAIN, ++ DEFAULT_AMD_SUB_DOMAIN, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_LOCALHOST_ADDRESS, ++ DEFAULT_AMD_LOCALHOST_ADDRESS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_LOG_OPTIONS, ++ DEFAULT_AMD_LOG_OPTIONS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_MAP_DEFAULTS, ++ DEFAULT_AMD_MAP_DEFAULTS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_MAP_TYPE, ++ DEFAULT_AMD_MAP_TYPE, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_NIS_DOMAIN, ++ DEFAULT_AMD_NIS_DOMAIN, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_NORMALIZE_HOSTNAMES, ++ DEFAULT_AMD_NORMALIZE_HOSTNAMES, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_NORMALIZE_SLASHES, ++ DEFAULT_AMD_NORMALIZE_SLASHES, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_OS, host_os_name, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_RESTART_MOUNTS, ++ DEFAULT_AMD_RESTART_MOUNTS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_SEARCH_PATH, ++ DEFAULT_AMD_SEARCH_PATH, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ /* selectors_on_default is depricated, use selectors_in_defaults */ ++ ret = conf_update(sec, NAME_AMD_SELECTORS_ON_DEFAULT, ++ DEFAULT_AMD_SELECTORS_IN_DEFAULTS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_SELECTORS_IN_DEFAULTS, ++ DEFAULT_AMD_SELECTORS_IN_DEFAULTS, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_UMOUNT_ON_EXIT, ++ DEFAULT_AMD_UMOUNT_ON_EXIT, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AMD_VENDOR, ++ DEFAULT_AMD_VENDOR, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ return 1; ++ ++error: ++ return 0; ++} ++ + static int conf_add(const char *section, const char *key, const char *value, unsigned long flags) + { + struct conf_option *co; + char *sec, *name, *val, *tmp; + unsigned int size = CFG_TABLE_SIZE; + u_int32_t index; +- int ret; +- +- sec = name = val = NULL; +- +- co = conf_lookup(section, key); +- if (co) { +- ret = CFG_EXISTS; +- goto error; +- } ++ int ret = CFG_FAIL; + +- ret = CFG_FAIL; ++ sec = name = val = tmp = NULL; + + /* Environment overrides file value */ +- if (((flags & CFG_ENV) && (tmp = getenv(key))) || value) { ++ if (((flags & CONF_ENV) && (tmp = getenv(key))) || value) { + if (tmp) + val = strdup(tmp); +- else +- val = strdup(value); ++ else { ++ if (value) ++ val = strdup(value); ++ } + if (!val) + goto error; + } +@@ -335,7 +583,7 @@ static int conf_add(const char *section, const char *key, const char *value, uns + co->next = NULL; + + /* Don't change user set values in the environment */ +- if (flags & CONF_ENV) ++ if (flags & CONF_ENV && value) + setenv(name, value, 0); + + index = hash(key, size); +@@ -386,7 +634,7 @@ static void conf_delete(const char *section, const char *key) + + free(co->section); + free(co->name); +- if (co->value); ++ if (co->value) + free(co->value); + free(co); + } +@@ -403,13 +651,15 @@ static int conf_update(const char *section, + if (!co) + ret = conf_add(section, key, value, flags); + else { +- char *val = NULL, *tmp; ++ char *val = NULL, *tmp = NULL; + /* Environment overrides file value */ + if (((flags & CONF_ENV) && (tmp = getenv(key))) || value) { + if (tmp) + val = strdup(tmp); +- else +- val = strdup(value); ++ else { ++ if (value) ++ val = strdup(value); ++ } + if (!val) + goto error; + } +@@ -419,7 +669,7 @@ static int conf_update(const char *section, + if (flags) + co->flags = flags; + /* Don't change user set values in the environment */ +- if (flags & CONF_ENV) ++ if (flags & CONF_ENV && value) + setenv(key, value, 0); + } + +@@ -456,15 +706,39 @@ static struct conf_option *conf_lookup(const char *section, const char *key) + return co; + } + ++static unsigned int conf_section_exists(const char *section) ++{ ++ struct conf_option *co; ++ int ret; ++ ++ if (!section) ++ return 0; ++ ++ ret = 0; ++ pthread_mutex_lock(&conf_mutex); ++ co = conf_lookup(section, section); ++ if (co) ++ ret = 1; ++ pthread_mutex_unlock(&conf_mutex); ++ ++ return ret; ++} ++ + /* + * We've changed the key names so we need to check for the + * config key and it's old name for backward conpatibility. + */ +-static int check_set_config_value(const char *res, const char *value) ++static int check_set_config_value(const char *section, ++ const char *res, const char *value) + { +- const char *sec = autofs_gbl_sec; ++ const char *sec; + int ret; + ++ if (section) ++ sec = section; ++ else ++ sec = autofs_gbl_sec; ++ + if (!strcasecmp(res, NAME_LDAP_URI)) + ret = conf_add(sec, res, value, 0); + else if (!strcasecmp(res, NAME_SEARCH_BASE)) +@@ -475,14 +749,15 @@ static int check_set_config_value(const char *res, const char *value) + return ret; + } + +-static int parse_line(char *line, char **res, char **value) ++static int parse_line(char *line, char **sec, char **res, char **value) + { + char *key, *val, *trailer; ++ char *tmp; + int len; + + key = line; + +- if (*key == '#' || !isalpha(*key)) ++ if (*key == '#' || (*key != '[' && !isalpha(*key))) + return 0; + + while (*key && *key == ' ') +@@ -491,11 +766,34 @@ static int parse_line(char *line, char **res, char **value) + if (!*key) + return 0; + ++ if (*key == '[') { ++ char *tmp; ++ while (*key && (*key == '[' || *key == ' ')) ++ key++; ++ tmp = strchr(key, ']'); ++ if (!tmp) ++ return 0; ++ *tmp = ' '; ++ while (*tmp && *tmp == ' ') { ++ *tmp = '\0'; ++ tmp--; ++ } ++ *sec = key; ++ *res = NULL; ++ *value = NULL; ++ return 1; ++ } ++ + if (!(val = strchr(key, '='))) + return 0; + ++ tmp = val; ++ + *val++ = '\0'; + ++ while (*(--tmp) == ' ') ++ *tmp = '\0'; ++ + while (*val && (*val == '"' || isblank(*val))) + val++; + +@@ -515,12 +813,97 @@ static int parse_line(char *line, char **res, char **value) + while (*trailer && (*trailer == '"' || isblank(*trailer))) + *(trailer--) = '\0';; + ++ *sec = NULL; + *res = key; + *value = val; + + return 1; + } + ++static int read_config(unsigned int to_syslog, FILE *f, const char *name) ++{ ++ char buf[MAX_LINE_LEN]; ++ char secbuf[MAX_SECTION_NAME]; ++ char *new_sec; ++ char *res; ++ ++ new_sec = NULL; ++ while ((res = fgets(buf, MAX_LINE_LEN, f))) { ++ char *sec, *key, *value; ++ sec = key = value = NULL; ++ if (!parse_line(res, &sec, &key, &value)) ++ continue; ++ if (sec) { ++ strcpy(secbuf, sec); ++ new_sec = &secbuf[0]; ++ conf_update(sec, sec, NULL, 0); ++ continue; ++ } ++ if (!strcasecmp(res, NAME_AMD_MOUNT_TYPE)) { ++ message(to_syslog, ++ "%s is always autofs, ignored", res); ++ continue; ++ } ++ if (!strcasecmp(res, NAME_AMD_PID_FILE)) { ++ message(to_syslog, ++ "%s must be specified as a command line" ++ " option, ignored", res); ++ continue; ++ } ++ if (!strcasecmp(res, NAME_AMD_RESTART_MOUNTS)) { ++ message(to_syslog, ++ "%s is always done by autofs, ignored", res); ++ continue; ++ } ++ if (!strcasecmp(res, NAME_AMD_USE_TCPWRAPPERS) || ++ !strcasecmp(res, NAME_AMD_AUTO_ATTRCACHE) || ++ !strcasecmp(res, NAME_AMD_PRINT_PID) || ++ !strcasecmp(res, NAME_AMD_PRINT_VERSION) || ++ !strcasecmp(res, NAME_AMD_LOG_FILE) || ++ !strcasecmp(res, NAME_AMD_PREFERRED_AMQ_PORT) || ++ !strcasecmp(res, NAME_AMD_TRUNCATE_LOG) || ++ !strcasecmp(res, NAME_AMD_DEBUG_MTAB_FILE) || ++ !strcasecmp(res, NAME_AMD_DEBUG_OPTIONS) || ++ !strcasecmp(res, NAME_AMD_SUN_MAP_SYNTAX) || ++ !strcasecmp(res, NAME_AMD_PORTMAP_PROGRAM) || ++ !strcasecmp(res, NAME_AMD_NFS_VERS) || ++ !strcasecmp(res, NAME_AMD_NFS_VERS_PING) || ++ !strcasecmp(res, NAME_AMD_NFS_PROTO) || ++ !strcasecmp(res, NAME_AMD_NFS_ALLOW_ANY_INTERFACE) || ++ !strcasecmp(res, NAME_AMD_NFS_ALLOW_INSECURE_PORT) || ++ !strcasecmp(res, NAME_AMD_NFS_RETRANSMIT_COUNTER) || ++ !strcasecmp(res, NAME_AMD_NFS_RETRANSMIT_COUNTER_UDP) || ++ !strcasecmp(res, NAME_AMD_NFS_RETRANSMIT_COUNTER_TCP) || ++ !strcasecmp(res, NAME_AMD_NFS_RETRANSMIT_COUNTER_TOPLVL) || ++ !strcasecmp(res, NAME_AMD_NFS_RETRY_INTERVAL) || ++ !strcasecmp(res, NAME_AMD_NFS_RETRY_INTERVAL_UDP) || ++ !strcasecmp(res, NAME_AMD_NFS_RETRY_INTERVAL_TCP) || ++ !strcasecmp(res, NAME_AMD_NFS_RETRY_INTERVAL_TOPLVL) || ++ !strcasecmp(res, NAME_AMD_LDAP_CACHE_MAXMEM) || ++ !strcasecmp(res, NAME_AMD_LDAP_CACHE_SECONDS) || ++ !strcasecmp(res, NAME_AMD_LDAP_PROTO_VERSION) || ++ !strcasecmp(res, NAME_AMD_SHOW_STATFS_ENTRIES) || ++ !strcasecmp(res, NAME_AMD_CACHE_DURATION) || ++ !strcasecmp(res, NAME_AMD_MAP_RELOAD_INTERVAL) || ++ !strcasecmp(res, NAME_AMD_MAP_OPTIONS) || ++ !strcasecmp(res, NAME_AMD_PLOCK)) { ++ message(to_syslog, ++ "%s is not used by autofs, ignored", res); ++ continue; ++ } ++ check_set_config_value(new_sec, key, value); ++ } ++ ++ if (!feof(f) || ferror(f)) { ++ message(to_syslog, ++ "fgets returned error %d while reading config %s", ++ ferror(f), name); ++ return 0; ++ } ++ ++ return 0; ++} ++ + /* + * Read config env variables and check they have been set. + * +@@ -531,23 +914,11 @@ static int parse_line(char *line, char **res, char **value) + unsigned int defaults_read_config(unsigned int to_syslog) + { + FILE *f; +- char buf[MAX_LINE_LEN]; + struct stat stb; +- char *res; + int ret; + +- f = open_fopen_r(DEFAULT_CONFIG_FILE); +- if (!f) +- return 0; +- + pthread_mutex_lock(&conf_mutex); +- if (config) { +- if (fstat(fileno(f), &stb) != -1) { +- /* Config hasn't been updated */ +- if (stb.st_mtime <= config->modified) +- goto out; +- } +- } else { ++ if (!config) { + if (conf_init()) { + pthread_mutex_unlock(&conf_mutex); + message(to_syslog, "failed to init config"); +@@ -563,29 +934,39 @@ unsigned int defaults_read_config(unsigned int to_syslog) + return 0; + } + +- while ((res = fgets(buf, MAX_LINE_LEN, f))) { +- char *key, *value; +- if (!parse_line(res, &key, &value)) +- continue; +- check_set_config_value(key, value); ++ ret = conf_load_amd_defaults(); ++ if (!ret) { ++ pthread_mutex_unlock(&conf_mutex); ++ message(to_syslog, "failed to reset amd default config"); ++ return 0; ++ } ++ ++ f = open_fopen_r(DEFAULT_CONFIG_FILE); ++ if (!f) { ++ message(to_syslog, "failed to to open config %s", ++ DEFAULT_CONFIG_FILE); ++ goto out; ++ } ++ ++ if (fstat(fileno(f), &stb) != -1) { ++ /* Config hasn't been updated */ ++ if (stb.st_mtime <= config->modified) { ++ fclose(f); ++ goto out; ++ } + } + ++ ret = read_config(to_syslog, f, DEFAULT_CONFIG_FILE); ++ + if (fstat(fileno(f), &stb) != -1) + config->modified = stb.st_mtime; + else + message(to_syslog, "failed to update config modified time"); + +- if (!feof(f) || ferror(f)) { +- pthread_mutex_unlock(&conf_mutex); +- message(to_syslog, +- "fgets returned error %d while reading %s", +- ferror(f), DEFAULT_CONFIG_FILE); +- fclose(f); +- return 0; +- } ++ fclose(f); ++ + out: + pthread_mutex_unlock(&conf_mutex); +- fclose(f); + return 1; + } + +@@ -1101,3 +1482,269 @@ unsigned int defaults_get_map_hash_table_size(void) + return (unsigned int) size; + } + ++unsigned int conf_amd_mount_section_exists(const char *section) ++{ ++ return conf_section_exists(section); ++} ++ ++char *conf_amd_get_arch(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_ARCH); ++} ++ ++char *conf_amd_get_karch(void) ++{ ++ char *tmp = conf_get_string(amd_gbl_sec, NAME_AMD_KARCH); ++ if (!tmp) ++ tmp = conf_amd_get_arch(); ++ ++ return tmp; ++} ++ ++char *conf_amd_get_os(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_OS); ++} ++ ++char *conf_amd_get_os_ver(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_OSVER); ++} ++ ++char *conf_amd_get_vendor(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_VENDOR); ++} ++ ++char *conf_amd_get_full_os(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_FULL_OS); ++} ++ ++char *conf_amd_get_auto_dir(void) ++{ ++ char *tmp = conf_get_string(amd_gbl_sec, NAME_AMD_AUTO_DIR); ++ if (!tmp) ++ return strdup(DEFAULT_AMD_AUTO_DIR); ++ ++ return tmp; ++} ++ ++char *conf_amd_get_cluster(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_CLUSTER); ++} ++ ++unsigned int conf_amd_get_exec_map_timeout(void) ++{ ++ long tmp = conf_get_number(amd_gbl_sec, NAME_AMD_EXEC_MAP_TIMEOUT); ++ if (tmp == -1) ++ tmp = atoi(DEFAULT_AMD_EXEC_MAP_TIMEOUT); ++ ++ return (unsigned int) tmp; ++} ++ ++char *conf_amd_get_hesiod_base(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_HESIOD_BASE); ++} ++ ++char *conf_amd_get_ldap_base(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_LDAP_BASE); ++} ++ ++char *conf_amd_get_ldap_hostports(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_LDAP_HOSTPORTS); ++} ++ ++unsigned int conf_amd_get_ldap_proto_version(void) ++{ ++ long tmp = conf_get_number(amd_gbl_sec, NAME_AMD_LDAP_PROTO_VERSION); ++ if (tmp == -1) ++ tmp = atoi(DEFAULT_AMD_LDAP_PROTO_VERSION); ++ ++ return (unsigned int) tmp; ++} ++ ++char *conf_amd_get_sub_domain(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_SUB_DOMAIN); ++} ++ ++char *conf_amd_get_localhost_address(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_LOCALHOST_ADDRESS); ++} ++ ++unsigned int conf_amd_get_log_options(void) ++{ ++ int log_level = -1; ++ char *tmp = conf_get_string(amd_gbl_sec, NAME_AMD_LOG_OPTIONS); ++ if (tmp) { ++ if (strstr(tmp, "debug") || strstr(tmp, "all")) { ++ if (log_level < LOG_DEBUG) ++ log_level = LOG_DEBUG; ++ } ++ if (strstr(tmp, "info") || ++ strstr(tmp, "user") || ++ strcmp(tmp, "defaults")) { ++ if (log_level < LOG_INFO) ++ log_level = LOG_INFO; ++ } ++ if (strstr(tmp, "notice")) { ++ if (log_level < LOG_NOTICE) ++ log_level = LOG_NOTICE; ++ } ++ if (strstr(tmp, "warn") || ++ strstr(tmp, "map") || ++ strstr(tmp, "stats") || ++ strstr(tmp, "warning")) { ++ if (log_level < LOG_WARNING) ++ log_level = LOG_WARNING; ++ } ++ if (strstr(tmp, "error")) { ++ if (log_level < LOG_ERR) ++ log_level = LOG_ERR; ++ } ++ if (strstr(tmp, "fatal")) { ++ if (log_level < LOG_CRIT) ++ log_level = LOG_CRIT; ++ } ++ } ++ ++ if (log_level == -1) ++ log_level = LOG_ERR; ++ ++ return (unsigned int) log_level; ++} ++ ++char *conf_amd_get_nis_domain(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_NIS_DOMAIN); ++} ++ ++unsigned int conf_amd_set_nis_domain(const char *domain) ++{ ++ int ret; ++ ret = conf_update(amd_gbl_sec, NAME_AMD_NIS_DOMAIN, domain, CONF_NONE); ++ ++ return (unsigned int) ret; ++} ++ ++char *conf_amd_get_map_defaults(const char *section) ++{ ++ char *tmp = NULL; ++ if (section) ++ tmp = conf_get_string(section, NAME_AMD_MAP_DEFAULTS); ++ if (!tmp) ++ tmp = conf_get_string(amd_gbl_sec, NAME_AMD_MAP_DEFAULTS); ++ ++ return tmp; ++} ++ ++char *conf_amd_get_map_type(const char *section) ++{ ++ char *tmp = NULL; ++ if (section) ++ tmp = conf_get_string(section, NAME_AMD_MAP_TYPE); ++ if (!tmp) ++ tmp = conf_get_string(amd_gbl_sec, NAME_AMD_MAP_TYPE); ++ ++ return tmp; ++} ++ ++char *conf_amd_get_search_path(const char *section) ++{ ++ char *tmp = NULL; ++ if (section) ++ tmp = conf_get_string(section, NAME_AMD_SEARCH_PATH); ++ if (!tmp) ++ tmp = conf_get_string(amd_gbl_sec, NAME_AMD_SEARCH_PATH); ++ ++ return tmp; ++} ++ ++unsigned int conf_amd_get_dismount_interval(const char *section) ++{ ++ long tmp = -1; ++ if (section) ++ tmp = conf_get_number(section, NAME_AMD_DISMOUNT_INTERVAL); ++ if (tmp == -1) ++ tmp = conf_get_number(amd_gbl_sec, NAME_AMD_DISMOUNT_INTERVAL); ++ if (tmp == -1) ++ tmp = defaults_get_timeout(); ++ /* ++ * This won't happen as defaults_get_timeout() will return ++ * the autofs setting which is used if no other setting is ++ * found. ++ */ ++ if (tmp == -1) ++ tmp = atoi(DEFAULT_TIMEOUT); ++ ++ return (unsigned int) tmp; ++} ++ ++unsigned long conf_amd_get_flags(const char *section) ++{ ++ const char *amd = amd_gbl_sec; ++ unsigned long flags, tmp; ++ ++ /* Always true for us */ ++ flags = CONF_MOUNT_TYPE_AUTOFS; ++ ++ tmp = -1; ++ if (section) ++ tmp = conf_get_yesno(section, NAME_AMD_BROWSABLE_DIRS); ++ if (tmp == -1) ++ tmp = conf_get_yesno(amd, NAME_AMD_BROWSABLE_DIRS); ++ if (tmp) ++ flags |= CONF_BROWSABLE_DIRS; ++ ++ tmp = -1; ++ if (section) ++ tmp = conf_get_yesno(section, NAME_AMD_SELECTORS_IN_DEFAULTS); ++ if (tmp == -1) ++ tmp = conf_get_yesno(amd, NAME_AMD_SELECTORS_IN_DEFAULTS); ++ if (tmp) ++ flags |= CONF_SELECTORS_IN_DEFAULTS; ++ ++ tmp = conf_get_yesno(amd, NAME_AMD_NORMALIZE_HOSTNAMES); ++ if (tmp) ++ flags |= CONF_NORMALIZE_HOSTNAMES; ++ ++ tmp = conf_get_yesno(amd, NAME_AMD_RESTART_MOUNTS); ++ if (tmp) ++ flags |= CONF_RESTART_EXISTING_MOUNTS; ++ ++ tmp = conf_get_yesno(amd, NAME_AMD_FULLY_QUALIFIED_HOSTS); ++ if (tmp) ++ flags |= CONF_FULLY_QUALIFIED_HOSTS; ++ ++ tmp = conf_get_yesno(amd, NAME_AMD_UMOUNT_ON_EXIT); ++ if (tmp) ++ flags |= CONF_UNMOUNT_ON_EXIT; ++ ++ tmp = -1; ++ if (section) ++ tmp = conf_get_yesno(section, NAME_AMD_AUTOFS_USE_LOFS); ++ if (tmp == -1) ++ tmp = conf_get_yesno(amd, NAME_AMD_AUTOFS_USE_LOFS); ++ if (tmp) ++ flags |= CONF_AUTOFS_USE_LOFS; ++ ++ tmp = conf_get_yesno(amd, NAME_AMD_DOMAIN_STRIP); ++ if (tmp) ++ flags |= CONF_DOMAIN_STRIP; ++ ++ tmp = conf_get_yesno(amd, NAME_AMD_NORMALIZE_SLASHES); ++ if (tmp) ++ flags |= CONF_NORMALIZE_SLASHES; ++ ++ tmp = conf_get_yesno(amd, NAME_AMD_FORCED_UMOUNTS); ++ if (tmp) ++ flags |= CONF_FORCED_UNMOUNTS; ++ ++ return flags; ++} diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-cut-handling.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-cut-handling.patch new file mode 100644 index 0000000..afa2366 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-cut-handling.patch @@ -0,0 +1,49 @@ +autofs-5.0.9 - amd lookup add cut handling + +From: Ian Kent + +Now we have the added the selector handling we can add the cut location +handling. +--- + modules/parse_amd.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index d9c7d9b..5d8617e 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -1425,6 +1425,7 @@ int parse_mount(struct autofs_point *ap, const char *name, + struct map_source *source; + struct mapent_cache *mc; + struct mapent *me; ++ unsigned int at_least_one; + struct list_head entries, *p, *head; + struct amd_entry *defaults_entry; + struct amd_entry *cur_defaults; +@@ -1517,6 +1518,7 @@ int parse_mount(struct autofs_point *ap, const char *name, + goto done; + } + ++ at_least_one = 0; + head = &entries; + p = head->next; + while (p != head) { +@@ -1540,9 +1542,18 @@ int parse_mount(struct autofs_point *ap, const char *name, + continue; + } + ++ if (this->flags & AMD_ENTRY_CUT && at_least_one) { ++ info(ap->logopt, MODPREFIX ++ "at least one entry tried before cut selector, " ++ "not continuing"); ++ break; ++ } ++ + if (!match_selectors(ap->logopt, this, sv)) + continue; + ++ at_least_one = 1; ++ + update_with_defaults(cur_defaults, this, sv); + sv = expand_entry(ap, this, flags, sv); + sv = merge_entry_options(ap, this, sv); diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-expandamdent-function.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-expandamdent-function.patch new file mode 100644 index 0000000..75b570b --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-expandamdent-function.patch @@ -0,0 +1,259 @@ +autofs-5.0.9 - amd lookup add expandamdent() function + +From: Ian Kent + + +--- + include/parse_subs.h | 2 + lib/parse_subs.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 213 insertions(+) + +diff --git a/include/parse_subs.h b/include/parse_subs.h +index e57cf4a..675411d 100644 +--- a/include/parse_subs.h ++++ b/include/parse_subs.h +@@ -42,6 +42,8 @@ char *dequote(const char *, int, unsigned int); + int span_space(const char *, unsigned int); + char *sanitize_path(const char *, int, unsigned int, unsigned int); + char *merge_options(const char *, const char *); ++int expandamdent(const char *, char *, const struct substvar *); ++int expand_selectors(struct autofs_point *, const char *, char **, struct substvar *); + void free_map_type_info(struct map_type_info *); + struct map_type_info *parse_map_type_info(const char *); + +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index 99075b1..279f40e 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include "automount.h" + +@@ -39,6 +40,11 @@ static int volatile ifc_last_len = 0; + /* Get numeric value of the n bits starting at position p */ + #define getbits(x, p, n) ((x >> (p + 1 - n)) & ~(~0 << n)) + ++#define EXPAND_LEADING_SLASH 0x0001 ++#define EXPAND_TRAILING_SLASH 0x0002 ++#define EXPAND_LEADING_DOT 0x0004 ++#define EXPAND_TRAILING_DOT 0x0008 ++ + struct types { + char *type; + unsigned int len; +@@ -636,6 +642,211 @@ next: + return strdup(result); + } + ++static char *expand_slash_or_dot(char *str, unsigned int type) ++{ ++ char *val = NULL; ++ ++ if (!str) ++ return NULL; ++ ++ if (!type) ++ return str; ++ ++ if (type & EXPAND_LEADING_SLASH) ++ val = basename(str); ++ else if (type & EXPAND_TRAILING_SLASH) ++ val = dirname(str); ++ else if (type & (EXPAND_LEADING_DOT | EXPAND_TRAILING_DOT)) { ++ char *dot = strchr(str, '.'); ++ if (dot) ++ *dot++ = '\0'; ++ if (type & EXPAND_LEADING_DOT) ++ val = dot; ++ else ++ val = str; ++ } ++ ++ return val; ++} ++ ++/* ++ * $-expand an amd-style map entry and return the length of the entry. ++ * If "dst" is NULL, just count the length. ++ */ ++/* TODO: how should quoting be handled? */ ++int expandamdent(const char *src, char *dst, const struct substvar *svc) ++{ ++ unsigned int flags = conf_amd_get_flags(NULL); ++ const struct substvar *sv; ++ const char *o_src = src; ++ int len, l; ++ const char *p; ++ char ch; ++ ++ len = 0; ++ ++ while ((ch = *src++)) { ++ switch (ch) { ++ case '$': ++ if (*src == '{') { ++ char *start, *end; ++ unsigned int type = 0; ++ p = strchr(++src, '}'); ++ if (!p) { ++ /* Ignore rest of string */ ++ if (dst) ++ *dst = '\0'; ++ return len; ++ } ++ start = (char *) src; ++ if (*src == '/' || *src == '.') { ++ start++; ++ type = EXPAND_LEADING_SLASH; ++ if (*src == '.') ++ type = EXPAND_LEADING_DOT; ++ } ++ end = (char *) p; ++ if (*(p - 1) == '/' || *(p - 1) == '.') { ++ end--; ++ type = EXPAND_TRAILING_SLASH; ++ if (*(p - 1) == '.') ++ type = EXPAND_TRAILING_DOT; ++ } ++ sv = macro_findvar(svc, start, end - start); ++ if (sv) { ++ char *val; ++ char *str = strdup(sv->val); ++ val = expand_slash_or_dot(str, type); ++ if (!val) ++ val = sv->val; ++ l = strlen(val); ++ if (dst) { ++ if (*dst) ++ strcat(dst, val); ++ else ++ strcpy(dst, val); ++ dst += l; ++ } ++ len += l; ++ if (str) ++ free(str); ++ } else { ++ if (dst) { ++ *dst++ = ch; ++ *dst++ = '{'; ++ strncat(dst, src, p - src); ++ dst += (p - src); ++ *dst++ = '}'; ++ } ++ len += 1 + 1 + (p - src) + 1; ++ } ++ src = p + 1; ++ } else { ++ if (dst) ++ *(dst++) = ch; ++ len++; ++ } ++ break; ++ ++ case '\\': ++ if (!(flags & CONF_NORMALIZE_SLASHES)) { ++ len++; ++ if (dst) ++ *dst++ = ch; ++ break; ++ } ++ ++ if (*src) { ++ len++; ++ if (dst) ++ *dst++ = *src; ++ src++; ++ } ++ break; ++ ++ case '/': ++ len++; ++ if (dst) ++ *dst++ = ch; ++ ++ if (!(flags & CONF_NORMALIZE_SLASHES)) ++ break; ++ ++ /* Double slash at start is allowed */ ++ if (src == (o_src + 1) && *src == '/') { ++ len++; ++ if (dst) ++ *dst++ = *src; ++ src++; ++ } ++ while (*src == '/') ++ src++; ++ break; ++ ++ case '"': ++ len++; ++ if (dst) ++ *dst++ = ch; ++ ++ while (*src && *src != '"') { ++ len++; ++ if (dst) ++ *dst++ = *src; ++ src++; ++ } ++ if (*src) { ++ len++; ++ if (dst) ++ *dst++ = *src; ++ src++; ++ } ++ break; ++ ++ default: ++ if (dst) ++ *(dst++) = ch; ++ len++; ++ break; ++ } ++ } ++ if (dst) ++ *dst = '\0'; ++ ++ return len; ++} ++ ++int expand_selectors(struct autofs_point *ap, ++ const char *mapstr, char **pmapstr, ++ struct substvar *sv) ++{ ++ char buf[MAX_ERR_BUF]; ++ char *expand; ++ size_t len; ++ ++ if (!mapstr) ++ return 0; ++ ++ len = expandamdent(mapstr, NULL, sv); ++ if (len == 0) { ++ error(ap->logopt, "failed to expand map entry"); ++ return 0; ++ } ++ ++ expand = malloc(len + 1); ++ if (!expand) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, "malloc: %s", estr); ++ return 0; ++ } ++ memset(expand, 0, len + 1); ++ ++ expandamdent(mapstr, expand, sv); ++ ++ *pmapstr = expand; ++ ++ return len; ++} ++ + void free_map_type_info(struct map_type_info *info) + { + if (info->type) diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-external-mounts-tracking-functions.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-external-mounts-tracking-functions.patch new file mode 100644 index 0000000..727535d --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-external-mounts-tracking-functions.patch @@ -0,0 +1,188 @@ +autofs-5.0.9 - amd lookup add external mounts tracking functions + +From: Ian Kent + +Amd automounts can use what's called a sublink option. Using this +option a single containing mount can be specified and symlinks +that point to directories within the mount created instead of a +mount for every directory. + +In some cases this can greatly reduce the number of mounts needed +for a map but complicates automounting when using an "in-place" +automounter such as autofs. + +Clearly we can't perform the mount and create symlinks within it +so we must us a mount lookaside directory like amd. Those external +mounts also need to be managed. + +This patch adds functions to maintain a list of these mounts (much +like a reference counter) so we know if an external mount is present +and if it's time to umount it. +--- + include/mounts.h | 2 + + lib/mounts.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 134 insertions(+) + +diff --git a/include/mounts.h b/include/mounts.h +index c2f92ec..3bef086 100644 +--- a/include/mounts.h ++++ b/include/mounts.h +@@ -93,6 +93,8 @@ unsigned int get_kver_major(void); + unsigned int get_kver_minor(void); + char *make_options_string(char *path, int kernel_pipefd, const char *extra); + char *make_mnt_name_string(char *path); ++int ext_mount_add(struct list_head *, const char *); ++int ext_mount_remove(struct list_head *, const char *); + struct mnt_list *get_mnt_list(const char *table, const char *path, int include); + struct mnt_list *reverse_mnt_list(struct mnt_list *list); + void free_mnt_list(struct mnt_list *list); +diff --git a/lib/mounts.c b/lib/mounts.c +index 868dcb1..aea6691 100644 +--- a/lib/mounts.c ++++ b/lib/mounts.c +@@ -46,6 +46,17 @@ static const char mnt_name_template[] = "automount(pid%u)"; + static struct kernel_mod_version kver = {0, 0}; + static const char kver_options_template[] = "fd=%d,pgrp=%u,minproto=3,maxproto=5"; + ++#define EXT_MOUNTS_HASH_SIZE 50 ++ ++struct ext_mount { ++ char *mountpoint; ++ struct list_head mount; ++ struct list_head mounts; ++}; ++static struct list_head ext_mounts_hash[EXT_MOUNTS_HASH_SIZE]; ++static unsigned int ext_mounts_hash_init_done = 0; ++static pthread_mutex_t ext_mount_hash_mutex = PTHREAD_MUTEX_INITIALIZER; ++ + unsigned int linux_version_code(void) + { + struct utsname my_utsname; +@@ -422,6 +433,127 @@ char *make_mnt_name_string(char *path) + return mnt_name; + } + ++static void ext_mounts_hash_init(void) ++{ ++ int i; ++ for (i = 0; i < EXT_MOUNTS_HASH_SIZE; i++) ++ INIT_LIST_HEAD(&ext_mounts_hash[i]); ++ ext_mounts_hash_init_done = 1; ++} ++ ++static struct ext_mount *ext_mount_lookup(const char *mountpoint) ++{ ++ u_int32_t hval = hash(mountpoint, EXT_MOUNTS_HASH_SIZE); ++ struct list_head *p, *head; ++ ++ if (!ext_mounts_hash_init_done) ++ ext_mounts_hash_init(); ++ ++ if (list_empty(&ext_mounts_hash[hval])) ++ return NULL; ++ ++ head = &ext_mounts_hash[hval]; ++ list_for_each(p, head) { ++ struct ext_mount *this = list_entry(p, struct ext_mount, mount); ++ if (!strcmp(this->mountpoint, mountpoint)) ++ return this; ++ } ++ return NULL; ++} ++ ++int ext_mount_add(struct list_head *entry, const char *path) ++{ ++ struct ext_mount *em; ++ char *auto_dir; ++ u_int32_t hval; ++ int ret = 0; ++ ++ /* Not a mount in the external mount directory */ ++ auto_dir = conf_amd_get_auto_dir(); ++ if (strncmp(path, auto_dir, strlen(auto_dir))) { ++ free(auto_dir); ++ return 0; ++ } ++ free(auto_dir); ++ ++ pthread_mutex_lock(&ext_mount_hash_mutex); ++ ++ em = ext_mount_lookup(path); ++ if (em) { ++ struct list_head *p, *head; ++ head = &em->mounts; ++ list_for_each(p, head) { ++ if (p == entry) ++ goto done; ++ } ++ list_add_tail(entry, &em->mounts); ++ ret = 1; ++ goto done; ++ } ++ ++ em = malloc(sizeof(struct ext_mount)); ++ if (!em) { ++ ret = -1; ++ goto done; ++ } ++ ++ em->mountpoint = strdup(path); ++ if (!em->mountpoint) { ++ free(em); ++ ret = -1; ++ goto done; ++ } ++ INIT_LIST_HEAD(&em->mount); ++ INIT_LIST_HEAD(&em->mounts); ++ ++ hval = hash(path, EXT_MOUNTS_HASH_SIZE); ++ list_add_tail(&em->mount, &ext_mounts_hash[hval]); ++ ++ list_add_tail(entry, &em->mounts); ++ ++ ret = 1; ++done: ++ pthread_mutex_unlock(&ext_mount_hash_mutex); ++ return ret; ++} ++ ++int ext_mount_remove(struct list_head *entry, const char *path) ++{ ++ struct ext_mount *em; ++ char *auto_dir; ++ int ret = 0; ++ ++ /* Not a mount in the external mount directory */ ++ auto_dir = conf_amd_get_auto_dir(); ++ if (strncmp(path, auto_dir, strlen(auto_dir))) { ++ free(auto_dir); ++ return 0; ++ } ++ free(auto_dir); ++ ++ pthread_mutex_lock(&ext_mount_hash_mutex); ++ ++ em = ext_mount_lookup(path); ++ if (!em) ++ goto done; ++ ++ list_del_init(entry); ++ ++ if (!list_empty(&em->mounts)) ++ goto done; ++ else { ++ list_del_init(&em->mount); ++ if (list_empty(&em->mount)) { ++ free(em->mountpoint); ++ free(em); ++ } ++ ret = 1; ++ } ++done: ++ pthread_mutex_unlock(&ext_mount_hash_mutex); ++ return ret; ++} ++ + /* + * Get list of mounts under path in longest->shortest order + */ diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-handling-of-amd-maps-in-the-master-map.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-handling-of-amd-maps-in-the-master-map.patch new file mode 100644 index 0000000..f18e40d --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-handling-of-amd-maps-in-the-master-map.patch @@ -0,0 +1,361 @@ +autofs-5.0.9 - amd lookup add handling of amd maps in the master map + +From: Ian Kent + + +--- + daemon/automount.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++- + include/automount.h | 1 + + include/master.h | 2 + + lib/master.c | 44 +++++++++++++++++++++++++++ + lib/master_parse.y | 23 ++++++++++++-- + lib/master_tok.l | 2 + + lib/parse_subs.c | 1 + + modules/mount_autofs.c | 24 +++++++++++++++ + modules/parse_amd.c | 12 +++++++ + 9 files changed, 182 insertions(+), 6 deletions(-) + +diff --git a/daemon/automount.c b/daemon/automount.c +index fd5a19b..0ba3580 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -512,6 +512,9 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi + left++; + } + cache_multi_unlock(me->parent); ++ if (ap->entry->maps && ++ (ap->entry->maps->flags & MAP_FLAG_FORMAT_AMD)) ++ cache_pop_mapent(me); + pthread_setcancelstate(cur_state, NULL); + } + +@@ -525,13 +528,36 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi + * it already to ensure it's ok to remove any offset triggers. + */ + if (!is_mm_root && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) { ++ struct amd_entry *entry; + debug(ap->logopt, "unmounting dir = %s", path); + if (umount_ent(ap, path)) { + warn(ap->logopt, "could not umount dir %s", path); + left++; ++ goto done; + } +- } + ++ /* Check for an external mount and umount if possible */ ++ mounts_mutex_lock(ap); ++ entry = __master_find_amdmount(ap, path); ++ if (!entry) { ++ mounts_mutex_unlock(ap); ++ goto done; ++ } ++ list_del(&entry->entries); ++ mounts_mutex_unlock(ap); ++ if (ext_mount_remove(&entry->ext_mount, entry->fs)) { ++ if (umount_ent(ap, entry->fs)) ++ debug(ap->logopt, ++ "failed to umount external mount %s", ++ entry->fs); ++ else ++ debug(ap->logopt, ++ "umounted external mount %s", ++ entry->fs); ++ } ++ free_amd_entry(entry); ++ } ++done: + return left; + } + +@@ -540,10 +566,55 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi + int umount_multi(struct autofs_point *ap, const char *path, int incl) + { + int is_autofs_fs; ++ struct stat st; + int left; + + debug(ap->logopt, "path %s incl %d", path, incl); + ++ if (lstat(path, &st)) { ++ warn(ap->logopt, ++ "failed to stat mount point directory %s", path); ++ return 1; ++ } ++ ++ /* if this is a symlink we can handle it now */ ++ if (S_ISLNK(st.st_mode)) { ++ struct amd_entry *entry; ++ if (st.st_dev != ap->dev) { ++ crit(ap->logopt, ++ "symlink %s has the wrong device, " ++ "possible race condition", path); ++ return 1; ++ } ++ debug(ap->logopt, "removing symlink %s", path); ++ if (unlink(path)) { ++ error(ap->logopt, ++ "failed to remove symlink %s", path); ++ return 1; ++ } ++ /* Check for an external mount and attempt umount if needed */ ++ mounts_mutex_lock(ap); ++ entry = __master_find_amdmount(ap, path); ++ if (!entry) { ++ mounts_mutex_unlock(ap); ++ return 0; ++ } ++ list_del(&entry->entries); ++ mounts_mutex_unlock(ap); ++ if (ext_mount_remove(&entry->ext_mount, entry->fs)) { ++ if (umount_ent(ap, entry->fs)) ++ debug(ap->logopt, ++ "failed to umount external mount %s", ++ entry->fs); ++ else ++ debug(ap->logopt, ++ "umounted external mount %s", ++ entry->fs); ++ } ++ free_amd_entry(entry); ++ return 0; ++ } ++ + is_autofs_fs = 0; + if (master_find_submount(ap, path)) + is_autofs_fs = 1; +@@ -1475,9 +1546,15 @@ static void handle_mounts_cleanup(void *arg) + clean = 1; + + if (submount) { ++ struct amd_entry *am; + /* We are finishing up */ + ap->parent->submnt_count--; + list_del_init(&ap->mounts); ++ am = __master_find_amdmount(ap->parent, ap->path); ++ if (am) { ++ list_del_init(&am->entries); ++ free_amd_entry(am); ++ } + } + + /* Don't signal the handler if we have already done so */ +diff --git a/include/automount.h b/include/automount.h +index 615efcc..37133fe 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -510,6 +510,7 @@ struct autofs_point { + struct autofs_point *parent; /* Owner of mounts list for submount */ + pthread_mutex_t mounts_mutex; /* Protect mount lists */ + struct list_head mounts; /* List of autofs mounts at current level */ ++ struct list_head amdmounts; /* List of non submount amd mounts */ + unsigned int submount; /* Is this a submount */ + unsigned int shutdown; /* Shutdown notification */ + unsigned int submnt_count; /* Number of submounts */ +diff --git a/include/master.h b/include/master.h +index 8833ddf..bcc8eeb 100644 +--- a/include/master.h ++++ b/include/master.h +@@ -104,6 +104,8 @@ void master_source_current_signal(struct master_mapent *); + struct master_mapent *master_find_mapent(struct master *, const char *); + struct autofs_point *__master_find_submount(struct autofs_point *, const char *); + struct autofs_point *master_find_submount(struct autofs_point *, const char *); ++struct amd_entry *__master_find_amdmount(struct autofs_point *, const char *); ++struct amd_entry *master_find_amdmount(struct autofs_point *, const char *); + struct master_mapent *master_new_mapent(struct master *, const char *, time_t); + void master_add_mapent(struct master *, struct master_mapent *); + void master_remove_mapent(struct master_mapent *); +diff --git a/lib/master.c b/lib/master.c +index df4aef6..5e4ab51 100644 +--- a/lib/master.c ++++ b/lib/master.c +@@ -120,6 +120,7 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt, + ap->submount = submount; + INIT_LIST_HEAD(&ap->mounts); + INIT_LIST_HEAD(&ap->submounts); ++ INIT_LIST_HEAD(&ap->amdmounts); + ap->shutdown = 0; + + status = pthread_mutex_init(&ap->mounts_mutex, NULL); +@@ -136,11 +137,26 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt, + + void master_free_autofs_point(struct autofs_point *ap) + { ++ struct list_head *p, *head; + int status; + + if (!ap) + return; + ++ mounts_mutex_lock(ap); ++ head = &ap->amdmounts; ++ p = head->next; ++ while (p != head) { ++ struct amd_entry *entry = list_entry(p, struct amd_entry, entries); ++ p = p->next; ++ if (!list_empty(&entry->ext_mount)) ++ ext_mount_remove(&entry->ext_mount, entry->fs); ++ if (!list_empty(&entry->entries)) ++ list_del(&entry->entries); ++ free(entry); ++ } ++ mounts_mutex_unlock(ap); ++ + status = pthread_mutex_destroy(&ap->mounts_mutex); + if (status) + fatal(status); +@@ -694,6 +710,34 @@ struct autofs_point *master_find_submount(struct autofs_point *ap, const char *p + return submount; + } + ++struct amd_entry *__master_find_amdmount(struct autofs_point *ap, const char *path) ++{ ++ struct list_head *head, *p; ++ ++ head = &ap->amdmounts; ++ list_for_each(p, head) { ++ struct amd_entry *entry; ++ ++ entry = list_entry(p, struct amd_entry, entries); ++ ++ if (!strcmp(entry->path, path)) ++ return entry; ++ } ++ ++ return NULL; ++} ++ ++struct amd_entry *master_find_amdmount(struct autofs_point *ap, const char *path) ++{ ++ struct amd_entry *entry; ++ ++ mounts_mutex_lock(ap); ++ entry = __master_find_amdmount(ap, path); ++ mounts_mutex_unlock(ap); ++ ++ return entry; ++} ++ + struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age) + { + struct master_mapent *entry; +diff --git a/lib/master_parse.y b/lib/master_parse.y +index 11caf5b..03aedf7 100644 +--- a/lib/master_parse.y ++++ b/lib/master_parse.y +@@ -790,12 +790,29 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne + } + } + ++ if (!format) { ++ if (conf_amd_mount_section_exists(path)) ++ format = strdup("amd"); ++ } ++ ++ if (format && !strcmp(format, "amd")) { ++ unsigned int loglevel = conf_amd_get_log_options(); ++ if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO) ++ logopt = LOGOPT_DEBUG; ++ else if (loglevel <= LOG_INFO && loglevel > LOG_ERR) ++ logopt = LOGOPT_VERBOSE; ++ } ++ ++ + if (timeout < 0) { + /* +- * If no timeout is given get the timout from first +- * map (if it exists). ++ * If no timeout is given get the timout from the ++ * first map (if it exists) or the config for amd ++ * maps. + */ +- if (entry->maps) ++ if (format && !strcmp(format, "amd")) ++ timeout = conf_amd_get_dismount_interval(path); ++ else if (entry->maps) + timeout = entry->maps->exp_timeout; + else + timeout = default_timeout; +diff --git a/lib/master_tok.l b/lib/master_tok.l +index a55cc76..d43c1dd 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -119,7 +119,7 @@ DNNAMESTR2 ([[:alnum:]_.\-]+) + INTMAP (-hosts|-null) + MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS})) + MULTISEP ([\-]{2}[[:blank:]]+) +-MTYPE ((file|program|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?(:{OPTWS}|{WS})) ++MTYPE ((file|program|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS})) + + + OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index de5319f..421d18c 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -109,6 +109,7 @@ static unsigned int map_type_count = sizeof(map_type)/sizeof(struct types); + static struct types format_type[] = { + { "sun", 3 }, + { "hesiod", 6 }, ++ { "amd", 3}, + }; + static unsigned int format_type_count = sizeof(format_type)/sizeof(struct types); + +diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c +index 61aec70..ab5a8e3 100644 +--- a/modules/mount_autofs.c ++++ b/modules/mount_autofs.c +@@ -203,6 +203,30 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, + } + if (info->map) + argv[0] = info->map; ++ /* ++ * If the parent map format is amd and the format isn't ++ * specified in the map entry set it from the parent map ++ * source. ++ */ ++ if (!info->format && ap->entry->maps) { ++ struct map_source *s = ap->entry->maps; ++ /* ++ * For amd maps, if the format and source type aren't ++ * specified try and set them from the parent. ++ */ ++ if (s->flags & MAP_FLAG_FORMAT_AMD) { ++ info->format = strdup("amd"); ++ if (!info->format) ++ warn(ap->logopt, MODPREFIX ++ "failed to set amd map format"); ++ if (!info->type && s->type) { ++ info->type = strdup(s->type); ++ if (!info->type) ++ warn(ap->logopt, MODPREFIX ++ "failed to set amd map type"); ++ } ++ } ++ } + + if (options) { + p = options; +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 5d8617e..4322479 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -1563,8 +1563,18 @@ int parse_mount(struct autofs_point *ap, const char *name, + dequote_entry(ap, this); + + rv = amd_mount(ap, name, this, source, sv, flags, ctxt); +- if (!rv) ++ mounts_mutex_lock(ap); ++ if (!rv) { ++ /* Add to the parent list of mounts */ ++ list_add_tail(&this->entries, &ap->amdmounts); ++ /* Mounted, leave it on the parent list */ ++ list_del_init(&this->list); ++ mounts_mutex_unlock(ap); + break; ++ } ++ /* Not mounted, remove it from the parent list */ ++ list_del_init(&this->entries); ++ mounts_mutex_unlock(ap); + } + free_amd_entry(cur_defaults); + diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-handling-of-unhandled-options.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-handling-of-unhandled-options.patch new file mode 100644 index 0000000..352b5e8 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-handling-of-unhandled-options.patch @@ -0,0 +1,202 @@ +autofs-5.0.9 - amd lookup add handling of unhandled options + +From: Ian Kent + +There are a number of map options that are either not yet implemented +or aren't planned on being supported. + +Add log message feedback for these. +--- + modules/amd_parse.y | 84 +++++++++++++++++++++++++++++++++++++++++++++++++-- + modules/amd_tok.l | 12 +++++-- + 2 files changed, 90 insertions(+), 6 deletions(-) + +diff --git a/modules/amd_parse.y b/modules/amd_parse.y +index cd69c49..77adbe5 100644 +--- a/modules/amd_parse.y ++++ b/modules/amd_parse.y +@@ -28,6 +28,7 @@ + + #include "automount.h" + #include "parse_amd.h" ++#include "log.h" + + #define MAX_OPTS_LEN 1024 + #define MAX_ERR_LEN 512 +@@ -45,6 +46,7 @@ static void local_free_vars(void); + + static int amd_error(const char *s); + static int amd_notify(const char *s); ++static int amd_info(const char *s); + static int amd_msg(const char *s); + + static int add_location(void); +@@ -59,6 +61,7 @@ static struct autofs_point *pap; + struct substvar *psv; + static char opts[MAX_OPTS_LEN]; + static void prepend_opt(char *, char *); ++static char msg_buf[MAX_ERR_LEN]; + + #define YYDEBUG 0 + +@@ -99,6 +102,7 @@ static int amd_fprintf(FILE *, char *, ...); + + %token MAP_OPTION + %token MAP_TYPE ++%token CACHE_OPTION + %token FS_TYPE + %token FS_OPTION + %token FS_OPT_VALUE +@@ -259,6 +263,20 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE + !strcmp($3, "ext4")) { + entry.flags |= AMD_MOUNT_TYPE_EXT; + entry.type = amd_strdup($3); ++ } else if (!strcmp($3, "jfs") || ++ !strcmp($3, "linkx") || ++ !strcmp($3, "nfsx") || ++ !strcmp($3, "nfsl") || ++ !strcmp($3, "program") || ++ !strcmp($3, "lustre") || ++ !strcmp($3, "direct")) { ++ sprintf(msg_buf, "file system type %s is " ++ "not yet implemented", $3); ++ amd_msg(msg_buf); ++ YYABORT; ++ } else if (!strcmp($3, "cachefs")) { ++ sprintf(msg_buf, "file syatem %s is not " ++ "supported by autofs, ignored", $3); + } else { + amd_notify($1); + YYABORT; +@@ -275,7 +293,18 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE + else if (!strcmp($3, "exec")) + /* autofs uses "program" for "exec" map type */ + entry.map_type = amd_strdup("program"); +- else { ++ else if (!strcmp($3, "passwd")) { ++ sprintf(msg_buf, "map type %s is " ++ "not yet implemented", $3); ++ amd_msg(msg_buf); ++ YYABORT; ++ } else if (!strcmp($3, "ndbm") || ++ !strcmp($3, "union")) { ++ sprintf(msg_buf, "map type %s is not " ++ "supported by autofs", $3); ++ amd_msg(msg_buf); ++ YYABORT; ++ } else { + amd_notify($1); + YYABORT; + } +@@ -304,7 +333,17 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE + entry.rfs = amd_strdup($3); + else if (!strcmp($1, "dev")) + entry.dev = amd_strdup($3); +- else { ++ else if (!strcmp($1, "mount") || ++ !strcmp($1, "unmount") || ++ !strcmp($1, "umount")) { ++ amd_info("file system type program is not " ++ "yet implemented, option ignored"); ++ YYABORT; ++ } else if (!strcmp($1, "delay") || ++ !strcmp($1, "cachedir")) { ++ sprintf(msg_buf, "option %s is not used by autofs", $1); ++ amd_info(msg_buf); ++ } else { + amd_notify($1); + YYABORT; + } +@@ -326,11 +365,44 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE + YYABORT; + } + } ++ | MAP_OPTION OPTION_ASSIGN CACHE_OPTION ++ { ++ sprintf(msg_buf, "option %s is not used, autofs " ++ "default caching is always used", $1); ++ amd_info(msg_buf); ++ } + ; + + options: OPTION + { +- prepend_opt(opts, $1); ++ if (!strcmp($1, "browsable") || ++ !strcmp($1, "fullybrowsable") || ++ !strcmp($1, "nounmount") || ++ !strcmp($1, "unmount")) { ++ sprintf(msg_buf, "option %s is not currently " ++ "implemented, ignored", $1); ++ amd_info(msg_buf); ++ } else if (!strncmp($1, "ping=", 5) || ++ !strncmp($1, "retry=", 6) || ++ !strcmp($1, "public") || ++ !strcmp($1, "softlookup") || ++ !strcmp($1, "xlatecookie")) { ++ sprintf(msg_buf, "option %s is not used by " ++ "autofs, ignored", $1); ++ amd_info(msg_buf); ++ } else if (!strncmp($1, "utimeout=", 9)) { ++ if (entry.flags & AMD_MOUNT_TYPE_AUTO) { ++ char *opt = $1; ++ prepend_opt(opts, ++opt); ++ } else { ++ sprintf(msg_buf, "umount timeout can't be " ++ "used for other than type " ++ "\"auto\" with autofs, " ++ "ignored"); ++ amd_info(msg_buf); ++ } ++ } else ++ prepend_opt(opts, $1); + } + | OPTION COMMA options + { +@@ -387,6 +459,12 @@ static int amd_notify(const char *s) + return(0); + } + ++static int amd_info(const char *s) ++{ ++ info(pap->logopt, "%s\n", s); ++ return 0; ++} ++ + static int amd_msg(const char *s) + { + logmsg("%s\n", s); +diff --git a/modules/amd_tok.l b/modules/amd_tok.l +index fdc8899..8a6d40c 100644 +--- a/modules/amd_tok.l ++++ b/modules/amd_tok.l +@@ -94,13 +94,14 @@ OPTS ({OSTR}(=({VSTR}|{QSTR}|{MACRO})+)?) + SOPT (({SSTR}|{QSTR}|{MACRO})+) + NOPT ({SSTR}|(({IP4ADDR}(\/{V4MASK})?)|({IP6ADDR}(\/{V6MASK})?))) + +-MAPOPT (fs|type|maptype|pref|sublink|delay) ++MAPOPT (fs|type|maptype|pref|sublink|cache) + MNTOPT (opts|addopts|remopts) +-FSOPTS (rhost|rfs|dev|cachedir) ++FSOPTS (rhost|rfs|dev|cachedir|mount|unmount|umount|delay) ++CHEOPT (mapdefault|none|inc|re|regexp|all) + MAPTYPE (file|nis|nisplus|ldap|hesiod|exec|ndbm|passwd|union) + FSTYPE_LOCAL (link|linkx|lofs|ext2|ext3|ext4|xfs|jfs|cachefs) + FSTYPE_NET (nfs|nfsx|nfsl|host) +-FSTYPE (auto|program|direct|{FSTYPE_LOCAL}|{FSTYPE_NET}) ++FSTYPE (auto|program|direct|lustre|{FSTYPE_LOCAL}|{FSTYPE_NET}) + + OSSEL (arch|karch|os|osver|full_os|vendor) + HSTSEL (host|hostd|domain|byte|cluster) +@@ -204,6 +205,11 @@ CUTSEP (\|\||\/) + return MAP_TYPE; + } + ++ {CHEOPT} { ++ strcpy(amd_lval.strtype, amd_text); ++ return CACHE_OPTION; ++ } ++ + {FOPT} { + strcpy(amd_lval.strtype, amd_text); + return FS_OPT_VALUE; diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-key-matching-helper-function.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-key-matching-helper-function.patch new file mode 100644 index 0000000..1627e04 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-key-matching-helper-function.patch @@ -0,0 +1,119 @@ +autofs-5.0.9 - amd lookup add key matching helper function + +From: Ian Kent + +Add helper function and match_cached_key() that perform the progressive +key+prefix matching procedure. +--- + include/parse_subs.h | 2 + + lib/parse_subs.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 86 insertions(+) + +diff --git a/include/parse_subs.h b/include/parse_subs.h +index 43da182..1e87716 100644 +--- a/include/parse_subs.h ++++ b/include/parse_subs.h +@@ -113,6 +113,8 @@ struct map_type_info { + unsigned int get_proximity(struct sockaddr *); + unsigned int get_network_proximity(const char *); + unsigned int in_network(char *); ++struct mapent *match_cached_key(struct autofs_point *, const char *, ++ struct map_source *, const char *); + const char *skipspace(const char *); + int check_colon(const char *); + int chunklen(const char *, int); +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index 421d18c..1e4825d 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -498,6 +498,90 @@ unsigned int in_network(char *network) + return 1; + } + ++struct mapent *match_cached_key(struct autofs_point *ap, ++ const char *err_prefix, ++ struct map_source *source, ++ const char *key) ++{ ++ char buf[MAX_ERR_BUF]; ++ struct mapent_cache *mc; ++ struct mapent *me; ++ ++ mc = source->mc; ++ ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { ++ int ret; ++ ++ me = cache_lookup(mc, key); ++ /* ++ * Stale mapent => check for entry in alternate source or ++ * wildcard. Note, plus included direct mount map entries ++ * are included as an instance (same map entry cache), not ++ * in a distinct source. ++ */ ++ if (me && (!me->mapent || ++ (me->source != source && *me->key != '/'))) { ++ while ((me = cache_lookup_key_next(me))) ++ if (me->source == source) ++ break; ++ if (!me) ++ me = cache_lookup_distinct(mc, "*"); ++ } ++ ++ if (!me) ++ goto done; ++ ++ /* ++ * If this is a lookup add wildcard match for later validation ++ * checks and negative cache lookups. ++ */ ++ if (!(ap->flags & MOUNT_FLAG_REMOUNT) && ++ ap->type == LKP_INDIRECT && *me->key == '*') { ++ ret = cache_update(mc, source, key, me->mapent, me->age); ++ if (!(ret & (CHE_OK | CHE_UPDATED))) ++ me = NULL; ++ } ++ } else { ++ char *lkp_key = strdup(key); ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, "%s strdup: %s", err_prefix, estr); ++ return NULL; ++ } ++ ++ /* If it's found we're done */ ++ me = cache_lookup_distinct(mc, lkp_key); ++ if (me) ++ goto free; ++ ++ /* ++ * Otherwise strip successive directory components and try ++ * a match against map entries ending with a wildcard and ++ * finally try the wilcard entry itself. ++ */ ++ while (!me) { ++ char *prefix; ++ ++ while ((prefix = strrchr(lkp_key, '/'))) { ++ *prefix = '\0'; ++ me = cache_partial_match_wild(mc, lkp_key); ++ if (me) ++ goto free; ++ } ++ ++ me = cache_lookup_distinct(mc, "*"); ++ if (me) ++ goto free; ++ ++ break; ++ } ++free: ++ free(lkp_key); ++ } ++done: ++ return me; ++} ++ + /* + * Skip whitespace in a string; if we hit a #, consider the rest of the + * entry a comment. diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-lofs-ext-and-xfs-fs-types.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-lofs-ext-and-xfs-fs-types.patch new file mode 100644 index 0000000..c6c4f76 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-lofs-ext-and-xfs-fs-types.patch @@ -0,0 +1,167 @@ +autofs-5.0.9 - amd lookup add fs types lofs, ext, and xfs + +From: Ian Kent + + +--- + include/parse_amd.h | 9 +++++++++ + modules/amd_parse.y | 13 +++++++++++++ + modules/amd_tok.l | 4 +++- + modules/parse_amd.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 75 insertions(+), 1 deletion(-) + +diff --git a/include/parse_amd.h b/include/parse_amd.h +index a8521b5..4015e9f 100644 +--- a/include/parse_amd.h ++++ b/include/parse_amd.h +@@ -20,6 +20,14 @@ + #define AMD_MOUNT_TYPE_NFS 0x00000002 + #define AMD_MOUNT_TYPE_LINK 0x00000004 + #define AMD_MOUNT_TYPE_HOST 0x00000008 ++#define AMD_MOUNT_TYPE_NFSL 0x00000010 ++#define AMD_MOUNT_TYPE_NFSX 0x00000020 ++#define AMD_MOUNT_TYPE_LINKX 0x00000040 ++#define AMD_MOUNT_TYPE_LOFS 0x00000080 ++#define AMD_MOUNT_TYPE_EXT 0x00000100 ++#define AMD_MOUNT_TYPE_XFS 0x00000200 ++#define AMD_MOUNT_TYPE_JFS 0x00000400 ++#define AMD_MOUNT_TYPE_CACHEFS 0x00000800 + #define AMD_MOUNT_TYPE_MASK 0x0000ffff + + #define AMD_ENTRY_CUT 0x00010000 +@@ -38,6 +46,7 @@ struct amd_entry { + char *fs; + char *rhost; + char *rfs; ++ char *dev; + char *opts; + char *addopts; + char *remopts; +diff --git a/modules/amd_parse.y b/modules/amd_parse.y +index 71fd569..cd69c49 100644 +--- a/modules/amd_parse.y ++++ b/modules/amd_parse.y +@@ -248,6 +248,17 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE + } else if (!strcmp($3, "host")) { + entry.flags |= AMD_MOUNT_TYPE_HOST; + entry.type = amd_strdup($3); ++ } else if (!strcmp($3, "lofs")) { ++ entry.flags |= AMD_MOUNT_TYPE_LOFS; ++ entry.type = amd_strdup("bind"); ++ } else if (!strcmp($3, "xfs")) { ++ entry.flags |= AMD_MOUNT_TYPE_XFS; ++ entry.type = amd_strdup($3); ++ } else if (!strcmp($3, "ext2") || ++ !strcmp($3, "ext3") || ++ !strcmp($3, "ext4")) { ++ entry.flags |= AMD_MOUNT_TYPE_EXT; ++ entry.type = amd_strdup($3); + } else { + amd_notify($1); + YYABORT; +@@ -291,6 +302,8 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE + entry.rhost = amd_strdup($3); + else if (!strcmp($1, "rfs")) + entry.rfs = amd_strdup($3); ++ else if (!strcmp($1, "dev")) ++ entry.dev = amd_strdup($3); + else { + amd_notify($1); + YYABORT; +diff --git a/modules/amd_tok.l b/modules/amd_tok.l +index cea9ea5..fdc8899 100644 +--- a/modules/amd_tok.l ++++ b/modules/amd_tok.l +@@ -98,7 +98,9 @@ MAPOPT (fs|type|maptype|pref|sublink|delay) + MNTOPT (opts|addopts|remopts) + FSOPTS (rhost|rfs|dev|cachedir) + MAPTYPE (file|nis|nisplus|ldap|hesiod|exec|ndbm|passwd|union) +-FSTYPE (auto|nfs|link|host|nfsx|ufs|xfs|efs) ++FSTYPE_LOCAL (link|linkx|lofs|ext2|ext3|ext4|xfs|jfs|cachefs) ++FSTYPE_NET (nfs|nfsx|nfsl|host) ++FSTYPE (auto|program|direct|{FSTYPE_LOCAL}|{FSTYPE_NET}) + + OSSEL (arch|karch|os|osver|full_os|vendor) + HSTSEL (host|hostd|domain|byte|cluster) +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 4322479..e27a195 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -598,6 +598,12 @@ static void update_with_defaults(struct amd_entry *defaults, + } + } + ++ if (!entry->dev && defaults->dev) { ++ tmp = strdup(defaults->dev); ++ if (tmp) ++ entry->dev = tmp; ++ } ++ + if (!entry->opts && defaults->opts) { + tmp = merge_options(defaults->opts, entry->opts); + if (tmp) +@@ -949,6 +955,35 @@ out: + return ret; + } + ++static int do_generic_mount(struct autofs_point *ap, const char *name, ++ struct amd_entry *entry, const char *target, ++ unsigned int flags) ++{ ++ int ret = 0; ++ ++ if (!entry->sublink) { ++ ret = do_mount(ap, ap->path, name, strlen(name), ++ target, entry->type, entry->opts); ++ } else { ++ /* ++ * Careful, external mounts may get mounted ++ * multiple times since they are outside of ++ * the automount filesystem. ++ */ ++ if (!is_mounted(_PATH_MOUNTED, entry->fs, MNTS_REAL)) { ++ ret = do_mount(ap, entry->fs, "/", 1, ++ target, entry->type, entry->opts); ++ if (ret) ++ goto out; ++ } ++ /* We might be using an external mount */ ++ ext_mount_add(&entry->ext_mount, entry->fs); ++ ret = do_link_mount(ap, name, entry, flags); ++ } ++out: ++ return ret; ++} ++ + static int do_nfs_mount(struct autofs_point *ap, const char *name, + struct amd_entry *entry, unsigned int flags) + { +@@ -1024,6 +1059,15 @@ static int amd_mount(struct autofs_point *ap, const char *name, + ret = do_auto_mount(ap, name, entry, flags); + break; + ++ case AMD_MOUNT_TYPE_LOFS: ++ ret = do_generic_mount(ap, name, entry, entry->rfs, flags); ++ break; ++ ++ case AMD_MOUNT_TYPE_EXT: ++ case AMD_MOUNT_TYPE_XFS: ++ ret = do_generic_mount(ap, name, entry, entry->dev, flags); ++ break; ++ + case AMD_MOUNT_TYPE_NFS: + ret = do_nfs_mount(ap, name, entry, flags); + break; +@@ -1260,6 +1304,12 @@ static struct amd_entry *dup_defaults_entry(struct amd_entry *defaults) + entry->rhost = tmp; + } + ++ if (defaults->dev) { ++ tmp = strdup(defaults->dev); ++ if (tmp) ++ entry->dev = tmp; ++ } ++ + if (defaults->opts) { + tmp = strdup(defaults->opts); + if (tmp) diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-lookup-vars.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-lookup-vars.patch new file mode 100644 index 0000000..11659d5 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-lookup-vars.patch @@ -0,0 +1,202 @@ +autofs-5.0.9 - amd lookup add lookup vars + +From: Ian Kent + + +--- + modules/parse_amd.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 141 insertions(+), 16 deletions(-) + +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 295a10f..35cc5dc 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -129,6 +129,100 @@ int parse_init(int argc, const char *const *argv, void **context) + return 0; + } + ++static struct substvar *add_lookup_vars(struct autofs_point *ap, ++ const char *key, int key_len, ++ struct map_source *source, ++ struct substvar *sv) ++{ ++ struct substvar *list = sv; ++ struct thread_stdenv_vars *tsv; ++ char lkp_key[PATH_MAX + 1]; ++ char path[PATH_MAX + 1]; ++ struct mapent *me; ++ int len; ++ ++ len = strlen(ap->path) + 1 + key_len + 1; ++ if (len > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: lookup key is greater than PATH_MAX"); ++ return NULL; ++ } ++ ++ if (ap->pref) { ++ if (snprintf(lkp_key, sizeof(lkp_key), "%s%s", ++ ap->pref, key) >= sizeof(lkp_key)) { ++ error(ap->logopt, MODPREFIX "key too long"); ++ return NULL; ++ } ++ } else { ++ if (snprintf(lkp_key, sizeof(lkp_key), "%s", ++ key) >= sizeof(lkp_key)) { ++ error(ap->logopt, MODPREFIX "key too long"); ++ return NULL; ++ } ++ } ++ ++ if (*key == '/') ++ strcpy(path, key); ++ else { ++ strcpy(path, ap->path); ++ strcat(path, "/"); ++ strcat(path, key); ++ } ++ list = macro_addvar(list, "path", 4, path); ++ ++ me = cache_lookup_distinct(source->mc, lkp_key); ++ if (me) ++ list = macro_addvar(list, "key", 3, me->key); ++ ++ while (!me) { ++ char match[PATH_MAX + 1]; ++ char *prefix; ++ ++ strcpy(match, lkp_key); ++ while ((prefix = strrchr(match, '/'))) { ++ *prefix = '\0'; ++ me = cache_partial_match_wild(source->mc, match); ++ if (me) { ++ list = macro_addvar(list, "key", 3, lkp_key); ++ break; ++ } ++ } ++ ++ if (!me) { ++ me = cache_lookup_distinct(source->mc, "*"); ++ if (me) ++ list = macro_addvar(list, "key", 3, lkp_key); ++ } ++ ++ break; ++ } ++ ++ if (source->argv[0][0]) ++ list = macro_addvar(list, "map", 3, source->argv[0]); ++ ++ tsv = pthread_getspecific(key_thread_stdenv_vars); ++ if (tsv) { ++ char numbuf[16]; ++ long num; ++ int ret; ++ ++ num = (long) tsv->uid; ++ ret = sprintf(numbuf, "%ld", num); ++ if (ret > 0) ++ list = macro_addvar(list, "uid", 3, numbuf); ++ num = (long) tsv->gid; ++ ret = sprintf(numbuf, "%ld", num); ++ if (ret > 0) ++ list = macro_addvar(list, "gid", 3, numbuf); ++ } ++ ++ list = macro_addvar(list, "fs", 2, "${autodir}/${rhost}${rfs}"); ++ list = macro_addvar(list, "rfs", 3, path); ++ ++ return list; ++} ++ + static void update_with_defaults(struct amd_entry *defaults, + struct amd_entry *entry, + struct substvar *sv) +@@ -167,22 +261,40 @@ static void update_with_defaults(struct amd_entry *defaults, + entry->pref = tmp; + } + +- if (!entry->fs && defaults->fs) { +- tmp = strdup(defaults->fs); +- if (tmp) +- entry->fs = tmp; ++ if (!entry->fs) { ++ if (defaults->fs) { ++ tmp = strdup(defaults->fs); ++ if (tmp) ++ entry->fs = tmp; ++ } else { ++ v = macro_findvar(sv, "fs", 2); ++ if (v) ++ entry->fs = strdup(v->val); ++ } + } + +- if (!entry->rfs && defaults->rfs) { +- tmp = strdup(defaults->rfs); +- if (tmp) +- entry->rfs = tmp; ++ if (!entry->rfs) { ++ if (defaults->rfs) { ++ tmp = strdup(defaults->rfs); ++ if (tmp) ++ entry->rfs = tmp; ++ } else { ++ v = macro_findvar(sv, "rfs", 3); ++ if (v) ++ entry->rfs = strdup(v->val); ++ } + } + +- if (!entry->rhost && defaults->rhost) { +- tmp = strdup(defaults->rhost); +- if (tmp) +- entry->rhost = tmp; ++ if (!entry->rhost) { ++ if (defaults->rhost) { ++ tmp = strdup(defaults->rhost); ++ if (tmp) ++ entry->rhost = tmp; ++ } else { ++ v = macro_findvar(sv, "host", 4); ++ if (v) ++ entry->rhost = strdup(v->val); ++ } + } + + if (!entry->opts && defaults->opts) { +@@ -197,10 +309,16 @@ static void update_with_defaults(struct amd_entry *defaults, + entry->addopts = tmp; + } + +- if (!entry->remopts && defaults->remopts) { +- tmp = merge_options(defaults->remopts, entry->remopts); +- if (tmp) +- entry->remopts = tmp; ++ if (!entry->remopts) { ++ if (defaults->remopts) { ++ tmp = strdup(defaults->remopts); ++ if (tmp) ++ entry->remopts = tmp; ++ } else { ++ v = macro_findvar(sv, "remopts", 7); ++ if (v) ++ entry->remopts = strdup(v->val); ++ } + } + + return; +@@ -984,6 +1102,13 @@ int parse_mount(struct autofs_point *ap, const char *name, + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + ++ sv = add_lookup_vars(ap, name, name_len, source, sv); ++ if (!sv) { ++ macro_free_table(sv); ++ pthread_setcancelstate(cur_state, NULL); ++ return 1; ++ } ++ + len = expand_selectors(ap, mapent, &pmapent, sv); + if (!len) { + macro_free_table(sv); diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-merge_options-function.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-merge_options-function.patch new file mode 100644 index 0000000..3a57fe8 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-merge_options-function.patch @@ -0,0 +1,153 @@ +autofs-5.0.9 - mad lookup add merge_options() function + +From: Ian Kent + + +--- + include/parse_subs.h | 1 + lib/parse_subs.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 114 insertions(+) + +diff --git a/include/parse_subs.h b/include/parse_subs.h +index c0da5ae..e57cf4a 100644 +--- a/include/parse_subs.h ++++ b/include/parse_subs.h +@@ -41,6 +41,7 @@ int strmcmp(const char *, const char *, int); + char *dequote(const char *, int, unsigned int); + int span_space(const char *, unsigned int); + char *sanitize_path(const char *, int, unsigned int, unsigned int); ++char *merge_options(const char *, const char *); + void free_map_type_info(struct map_type_info *); + struct map_type_info *parse_map_type_info(const char *); + +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index b77d890..99075b1 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -23,6 +23,9 @@ + #include + #include "automount.h" + ++#define MAX_OPTIONS_LEN 256 ++#define MAX_OPTION_LEN 40 ++ + #define MAX_NETWORK_LEN 255 + + #define MAX_IFC_BUF 2048 +@@ -523,6 +526,116 @@ char *sanitize_path(const char *path, int origlen, unsigned int type, unsigned i + return s_path; + } + ++static char *hasopt(const char *str, const char *opt) ++{ ++ const size_t optlen = strlen(opt); ++ char *rest = (char *) str, *p; ++ ++ while ((p = strstr(rest, opt)) != NULL) { ++ if ((p == rest || p[-1] == ',') && ++ (p[optlen] == '\0' || p[optlen] == '=' || ++ p[optlen] == ',')) ++ return p; ++ ++ rest = strchr (p, ','); ++ if (rest == NULL) ++ break; ++ ++rest; ++ } ++ ++ return NULL; ++} ++ ++char *merge_options(const char *opt1, const char *opt2) ++{ ++ char str[MAX_OPTIONS_LEN]; ++ char result[MAX_OPTIONS_LEN]; ++ char neg[MAX_OPTION_LEN]; ++ char *tok, *ptr = NULL; ++ size_t len; ++ ++ if (!opt1 && !opt2) ++ return NULL; ++ ++ if (!opt2) ++ return strdup(opt1); ++ ++ if (!opt1) ++ return strdup(opt2); ++ ++ if (!strcmp(opt1, opt2)) ++ return strdup(opt1); ++ ++ memset(result, 0, sizeof(result)); ++ strcpy(str, opt1); ++ ++ tok = strtok_r(str, ",", &ptr); ++ while (tok) { ++ const char *this = (const char *) tok; ++ char *eq = strchr(this, '='); ++ if (eq) { ++ *eq = '\0'; ++ if (!hasopt(opt2, this)) { ++ *eq = '='; ++ if (!*result) ++ strcpy(result, this); ++ else ++ strcat(result, this); ++ strcat(result, ","); ++ goto next; ++ } ++ } ++ ++ if (!strcmp(this, "rw") && hasopt(opt2, "ro")) ++ goto next; ++ if (!strcmp(this, "ro") && hasopt(opt2, "rw")) ++ goto next; ++ if (!strcmp(this, "bg") && hasopt(opt2, "fg")) ++ goto next; ++ if (!strcmp(this, "fg") && hasopt(opt2, "bg")) ++ goto next; ++ if (!strcmp(this, "bg") && hasopt(opt2, "fg")) ++ goto next; ++ if (!strcmp(this, "soft") && hasopt(opt2, "hard")) ++ goto next; ++ if (!strcmp(this, "hard") && hasopt(opt2, "soft")) ++ goto next; ++ ++ if (!strncmp(this, "no", 2)) { ++ strcpy(neg, this + 2); ++ if (hasopt(opt2, neg)) ++ goto next; ++ } else { ++ strcpy(neg, "no"); ++ strcat(neg, this); ++ if (hasopt(opt2, neg)) ++ goto next; ++ } ++ ++ if (hasopt(opt2, tok)) ++ goto next; ++ ++ if (!*result) ++ strcpy(result, this); ++ else ++ strcat(result, this); ++ strcat(result, ","); ++next: ++ tok = strtok_r(NULL, ",", &ptr); ++ } ++ ++ if (!*result) ++ strcpy(result, opt2); ++ else ++ strcat(result, opt2); ++ ++ len = strlen(result); ++ if (len && result[len - 1] == ',') ++ result[len - 1] = '\0'; ++ ++ return strdup(result); ++} ++ + void free_map_type_info(struct map_type_info *info) + { + if (info->type) diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-nfsl-and-linkx-fs-types.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-nfsl-and-linkx-fs-types.patch new file mode 100644 index 0000000..409626c --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-nfsl-and-linkx-fs-types.patch @@ -0,0 +1,123 @@ +autofs-5.0.9 - amd lookup add nfsl and linkx fs types + +From: Ian Kent + + +--- + modules/amd_parse.y | 8 ++++++-- + modules/parse_amd.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 60 insertions(+), 2 deletions(-) + +diff --git a/modules/amd_parse.y b/modules/amd_parse.y +index 77adbe5..1d4a0a3 100644 +--- a/modules/amd_parse.y ++++ b/modules/amd_parse.y +@@ -246,9 +246,15 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE + !strcmp($3, "nfs4")) { + entry.flags |= AMD_MOUNT_TYPE_NFS; + entry.type = amd_strdup($3); ++ } else if (!strcmp($3, "nfsl")) { ++ entry.flags |= AMD_MOUNT_TYPE_NFSL; ++ entry.type = amd_strdup($3); + } else if (!strcmp($3, "link")) { + entry.flags |= AMD_MOUNT_TYPE_LINK; + entry.type = amd_strdup($3); ++ } else if (!strcmp($3, "linkx")) { ++ entry.flags |= AMD_MOUNT_TYPE_LINKX; ++ entry.type = amd_strdup($3); + } else if (!strcmp($3, "host")) { + entry.flags |= AMD_MOUNT_TYPE_HOST; + entry.type = amd_strdup($3); +@@ -264,9 +270,7 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE + entry.flags |= AMD_MOUNT_TYPE_EXT; + entry.type = amd_strdup($3); + } else if (!strcmp($3, "jfs") || +- !strcmp($3, "linkx") || + !strcmp($3, "nfsx") || +- !strcmp($3, "nfsl") || + !strcmp($3, "program") || + !strcmp($3, "lustre") || + !strcmp($3, "direct")) { +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 4cebce8..7e04beb 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -955,6 +955,23 @@ out: + return ret; + } + ++static int do_linkx_mount(struct autofs_point *ap, const char *name, ++ struct amd_entry *entry, unsigned int flags) ++{ ++ struct stat st; ++ char *target; ++ ++ if (entry->sublink) ++ target = entry->sublink; ++ else ++ target = entry->fs; ++ ++ if (lstat(target, &st) < 0) ++ return errno; ++ ++ return do_link_mount(ap, name, entry, flags); ++} ++ + static int do_generic_mount(struct autofs_point *ap, const char *name, + struct amd_entry *entry, const char *target, + unsigned int flags) +@@ -1020,6 +1037,35 @@ out: + return ret; + } + ++static int do_nfsl_mount(struct autofs_point *ap, const char *name, ++ struct amd_entry *entry, struct substvar *sv, ++ unsigned int flags) ++{ ++ const struct substvar *host, *hostd; ++ struct stat st; ++ char *target; ++ ++ host = macro_findvar(sv, "host", 4); ++ if (!host) ++ return do_nfs_mount(ap, name, entry, flags); ++ hostd = macro_findvar(sv, "hostd", 5); ++ if (!hostd || !*hostd->val) ++ return do_nfs_mount(ap, name, entry, flags); ++ ++ if (entry->sublink) ++ target = entry->sublink; ++ else ++ target = entry->fs; ++ ++ if (strcasecmp(host->val, entry->rhost) || ++ strcasecmp(hostd->val, entry->rhost)) ++ return do_nfs_mount(ap, name, entry, flags); ++ else if (lstat(target, &st) < 0) ++ return do_nfs_mount(ap, name, entry, flags); ++ ++ return do_link_mount(ap, name, entry, flags); ++} ++ + static int do_host_mount(struct autofs_point *ap, const char *name, + struct amd_entry *entry, struct map_source *source, + unsigned int flags) +@@ -1078,10 +1124,18 @@ static int amd_mount(struct autofs_point *ap, const char *name, + ret = do_nfs_mount(ap, name, entry, flags); + break; + ++ case AMD_MOUNT_TYPE_NFSL: ++ ret = do_nfsl_mount(ap, name, entry, sv, flags); ++ break; ++ + case AMD_MOUNT_TYPE_LINK: + ret = do_link_mount(ap, name, entry, flags); + break; + ++ case AMD_MOUNT_TYPE_LINKX: ++ ret = do_linkx_mount(ap, name, entry, flags); ++ break; ++ + case AMD_MOUNT_TYPE_HOST: + ret = do_host_mount(ap, name, entry, source, flags); + break; diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-parent-prefix-handling.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-parent-prefix-handling.patch new file mode 100644 index 0000000..2000a55 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-parent-prefix-handling.patch @@ -0,0 +1,93 @@ +autofs-5.0.9 - amd lookup add parent prefix handling + +From: Ian Kent + + +--- + include/automount.h | 1 + + lib/master.c | 3 +++ + modules/parse_amd.c | 31 +++++++++++++++++++++++++++++++ + 3 files changed, 35 insertions(+) + +diff --git a/include/automount.h b/include/automount.h +index b304517..615efcc 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -491,6 +491,7 @@ struct kernel_mod_version { + struct autofs_point { + pthread_t thid; + char *path; /* Mount point name */ ++ char *pref; /* amd prefix */ + int pipefd; /* File descriptor for pipe */ + int kpipefd; /* Kernel end descriptor for pipe */ + int ioctlfd; /* File descriptor for ioctls */ +diff --git a/lib/master.c b/lib/master.c +index 4ac3c6a..df4aef6 100644 +--- a/lib/master.c ++++ b/lib/master.c +@@ -86,6 +86,7 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt, + free(ap); + return 0; + } ++ ap->pref = NULL; + + ap->entry = entry; + ap->exp_thread = 0; +@@ -144,6 +145,8 @@ void master_free_autofs_point(struct autofs_point *ap) + if (status) + fatal(status); + ++ if (ap->pref) ++ free(ap->pref); + free(ap->path); + free(ap); + } +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 54da1a5..295a10f 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -736,6 +736,36 @@ static void normalize_sublink(unsigned int logopt, + return; + } + ++/* ++ * Set the prefix. ++ * ++ * This is done in a couple of places, here is as good a place as ++ * any to describe it. ++ * ++ * If a prefix is present in the map entry then use it. ++ * ++ * A pref option with the value none is required to use no prefix, ++ * otherwise the prefix of the parent map, if any, will be used. ++ */ ++static void update_prefix(struct autofs_point *ap, ++ struct amd_entry *entry, const char *name) ++{ ++ size_t len; ++ char *new; ++ ++ if (!entry->pref && ap->pref) { ++ len = strlen(ap->pref) + strlen(name) + 2; ++ new = malloc(len); ++ if (new) { ++ strcpy(new, ap->pref); ++ strcat(new, name); ++ strcat(new, "/"); ++ entry->pref = new; ++ } ++ } ++ return; ++} ++ + static struct amd_entry *dup_defaults_entry(struct amd_entry *defaults) + { + struct amd_entry *entry; +@@ -1044,6 +1074,7 @@ int parse_mount(struct autofs_point *ap, const char *name, + sv = expand_entry(ap, this, flags, sv); + sv = merge_entry_options(ap, this, sv); + normalize_sublink(ap->logopt, this, sv); ++ update_prefix(ap, this, name); + + dequote_entry(ap, this); + diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-parse_amd-c.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-parse_amd-c.patch new file mode 100644 index 0000000..60b4eff --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-parse_amd-c.patch @@ -0,0 +1,2159 @@ +autofs-5.0.9 - amd lookup add parse_amd.c + +From: Ian Kent + +Add a yacc parser and an autofs parser module for amd format +maps. +--- + include/automount.h | 1 + include/mounts.h | 6 + include/parse_amd.h | 54 ++ + lib/mounts.c | 81 +++ + modules/Makefile | 21 - + modules/amd_parse.y | 511 ++++++++++++++++++++++++ + modules/amd_tok.l | 316 +++++++++++++++ + modules/parse_amd.c | 1081 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 8 files changed, 2069 insertions(+), 2 deletions(-) + create mode 100644 include/parse_amd.h + create mode 100644 modules/amd_parse.y + create mode 100644 modules/amd_tok.l + create mode 100644 modules/parse_amd.c + +--- autofs-5.0.7.orig/include/automount.h ++++ autofs-5.0.7/include/automount.h +@@ -34,6 +34,7 @@ + #include "parse_subs.h" + #include "mounts.h" + #include "dev-ioctl-lib.h" ++#include "parse_amd.h" + + #ifdef WITH_DMALLOC + #include +--- autofs-5.0.7.orig/include/mounts.h ++++ autofs-5.0.7/include/mounts.h +@@ -85,10 +85,16 @@ unsigned int linux_version_code(void); + int check_nfs_mount_version(struct nfs_mount_vers *, struct nfs_mount_vers *); + extern unsigned int nfs_mount_uses_string_options; + ++struct amd_entry; ++ + struct substvar *addstdenv(struct substvar *sv); + struct substvar *removestdenv(struct substvar *sv); + void add_std_amd_vars(struct substvar *sv); + void remove_std_amd_vars(void); ++struct amd_entry *new_amd_entry(const struct substvar *sv); ++void clear_amd_entry(struct amd_entry *entry); ++void free_amd_entry(struct amd_entry *entry); ++void free_amd_entry_list(struct list_head *entries); + + unsigned int query_kproto_ver(void); + unsigned int get_kver_major(void); +--- /dev/null ++++ autofs-5.0.7/include/parse_amd.h +@@ -0,0 +1,54 @@ ++/* ----------------------------------------------------------------------- * ++ * ++ * Copyright 2004-2006 Ian Kent ++ * Copyright 2013 Red Hat, Inc. ++ * All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, ++ * USA; either version 2 of the License, or (at your option) any later ++ * version; incorporated herein by reference. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++#ifndef PARSE_AMD_H ++#define PARSE_AMD_H ++ ++#define AMD_MOUNT_TYPE_NONE 0x00000000 ++#define AMD_MOUNT_TYPE_AUTO 0x00000001 ++#define AMD_MOUNT_TYPE_NFS 0x00000002 ++#define AMD_MOUNT_TYPE_LINK 0x00000004 ++#define AMD_MOUNT_TYPE_HOST 0x00000008 ++#define AMD_MOUNT_TYPE_MASK 0x0000ffff ++ ++#define AMD_ENTRY_CUT 0x00010000 ++#define AMD_ENTRY_MASK 0x00ff0000 ++ ++#define AMD_DEFAULTS_MERGE 0x01000000 ++#define AMD_DEFAULTS_RESET 0x02000000 ++#define AMD_DEFAULTS_MASK 0xff000000 ++ ++struct amd_entry { ++ char *path; ++ unsigned long flags; ++ char *type; ++ char *map_type; ++ char *pref; ++ char *fs; ++ char *rhost; ++ char *rfs; ++ char *opts; ++ char *addopts; ++ char *remopts; ++ char *sublink; ++ struct selector *selector; ++ struct list_head list; ++ struct list_head entries; ++ struct list_head ext_mount; ++}; ++ ++int amd_parse_list(struct autofs_point *, ++ const char *, struct list_head *, struct substvar **); ++ ++#endif +--- autofs-5.0.7.orig/lib/mounts.c ++++ autofs-5.0.7/lib/mounts.c +@@ -442,6 +442,87 @@ void remove_std_amd_vars(void) + return; + } + ++struct amd_entry *new_amd_entry(const struct substvar *sv) ++{ ++ struct amd_entry *new; ++ const struct substvar *v; ++ char *path; ++ ++ v = macro_findvar(sv, "path", 4); ++ if (!v) ++ return NULL; ++ ++ path = strdup(v->val); ++ if (!path) ++ return NULL; ++ ++ new = malloc(sizeof(struct amd_entry)); ++ if (!new) { ++ free(path); ++ return NULL; ++ } ++ ++ memset(new, 0, sizeof(*new)); ++ new->path = path; ++ INIT_LIST_HEAD(&new->list); ++ INIT_LIST_HEAD(&new->entries); ++ INIT_LIST_HEAD(&new->ext_mount); ++ ++ return new; ++} ++ ++void clear_amd_entry(struct amd_entry *entry) ++{ ++ if (!entry) ++ return; ++ if (entry->path) ++ free(entry->path); ++ if (entry->map_type) ++ free(entry->map_type); ++ if (entry->pref) ++ free(entry->pref); ++ if (entry->fs) ++ free(entry->fs); ++ if (entry->rhost) ++ free(entry->rhost); ++ if (entry->rfs) ++ free(entry->rfs); ++ if (entry->opts) ++ free(entry->opts); ++ if (entry->addopts) ++ free(entry->addopts); ++ if (entry->remopts) ++ free(entry->remopts); ++ if (entry->sublink) ++ free(entry->sublink); ++ if (entry->selector) ++ free_selector(entry->selector); ++ return; ++} ++ ++void free_amd_entry(struct amd_entry *entry) ++{ ++ clear_amd_entry(entry); ++ free(entry); ++ return; ++} ++ ++void free_amd_entry_list(struct list_head *entries) ++{ ++ if (!list_empty(entries)) { ++ struct list_head *head = entries; ++ struct amd_entry *this; ++ struct list_head *p; ++ ++ p = head->next; ++ while (p != head) { ++ this = list_entry(p, struct amd_entry, list); ++ p = p->next; ++ free_amd_entry(this); ++ } ++ } ++} ++ + /* + * Make common autofs mount options string + */ +--- autofs-5.0.7.orig/modules/Makefile ++++ autofs-5.0.7/modules/Makefile +@@ -7,16 +7,18 @@ include ../Makefile.rules + + SRCS := lookup_file.c lookup_program.c lookup_userhome.c \ + lookup_multi.c lookup_hosts.c lookup_dir.c \ +- parse_sun.c \ ++ parse_sun.c parse_amd.c \ + mount_generic.c mount_nfs.c mount_afs.c mount_autofs.c \ + mount_changer.c mount_bind.c + + MODS := lookup_file.so lookup_program.so lookup_userhome.so \ + lookup_multi.so lookup_hosts.so lookup_dir.so \ +- parse_sun.so \ ++ parse_sun.so parse_amd.so \ + mount_generic.so mount_nfs.so mount_afs.so mount_autofs.so \ + mount_changer.so mount_bind.so + ++YACCSRC = amd_tok.c amd_parse.tab.c amd_parse.tab.h \ ++ + ifeq ($(EXT2FS), 1) + SRCS += mount_ext2.c + MODS += mount_ext2.so +@@ -94,6 +96,21 @@ else ifeq ($(EXT4FS), 1) + mv $(INSTALLROOT)$(autofslibdir)/mount_ext2.so $(INSTALLROOT)$(autofslibdir)/mount_ext4.so + endif + ++amd_tok.c: amd_tok.l ++ $(LEX) -o$@ -Pamd_ $? ++ ++amd_tok.o: amd_tok.c amd_parse.tab.h ++ ++amd_parse.tab.c amd_parse.tab.h: amd_parse.y ++ $(YACC) -v -d -p amd_ -b amd_parse $? ++ ++amd_parse.tab.o: amd_parse.tab.c amd_parse.tab.h ++ ++parse_amd.so: parse_amd.c amd_parse.tab.o amd_tok.o ++ $(CC) $(LDFLAGS) $(SOLDFLAGS) $(CFLAGS) -o parse_amd.so \ ++ parse_amd.c amd_parse.tab.o amd_tok.o $(AUTOFS_LIB) $(LIBS) ++ $(STRIP) parse_amd.so ++ + # + # Ad hoc compilation rules for modules which need auxilliary libraries + # +--- /dev/null ++++ autofs-5.0.7/modules/amd_parse.y +@@ -0,0 +1,511 @@ ++%{ ++/* ----------------------------------------------------------------------- * ++ * ++ * Copyright 2013 Ian Kent ++ * Copyright 2013 Red Hat, Inc. ++ * All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, ++ * USA; either version 2 of the License, or (at your option) any later ++ * version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "automount.h" ++#include "parse_amd.h" ++ ++#define MAX_OPTS_LEN 1024 ++#define MAX_ERR_LEN 512 ++ ++static pthread_mutex_t parse_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++extern FILE *amd_in; ++extern char *amd_text; ++extern int amd_lex(void); ++extern void amd_set_scan_buffer(const char *); ++ ++static char *amd_strdup(char *); ++static void local_init_vars(void); ++static void local_free_vars(void); ++ ++static int amd_error(const char *s); ++static int amd_notify(const char *s); ++static int amd_msg(const char *s); ++ ++static int add_location(void); ++static int make_selector(char *name, ++ char *value1, char *value2, ++ unsigned int compare); ++static void add_selector(struct selector *selector); ++ ++static struct amd_entry entry; ++static struct list_head *entries; ++static struct autofs_point *pap; ++struct substvar *psv; ++static char opts[MAX_OPTS_LEN]; ++static void prepend_opt(char *, char *); ++ ++#define YYDEBUG 0 ++ ++#ifndef YYENABLE_NLS ++#define YYENABLE_NLS 0 ++#endif ++#ifndef YYLTYPE_IS_TRIVIAL ++#define YYLTYPE_IS_TRIVIAL 0 ++#endif ++ ++#if YYDEBUG ++static int amd_fprintf(FILE *, char *, ...); ++#undef YYFPRINTF ++#define YYFPRINTF amd_fprintf ++#endif ++ ++%} ++ ++%union { ++ char strtype[2048]; ++ int inttype; ++ long longtype; ++} ++ ++%token COMMENT ++%token SEPERATOR ++%token SPACE ++%token HYPHEN ++%token IS_EQUAL ++%token CUT ++%token NOT_EQUAL ++%token COMMA ++%token OPTION_ASSIGN ++%token NILL ++ ++%token MAP_OPTION ++%token MAP_TYPE ++%token FS_TYPE ++%token FS_OPTION ++%token FS_OPT_VALUE ++%token MNT_OPTION ++%token SELECTOR ++%token SELECTOR_VALUE ++%token OPTION ++%token MACRO ++%token OTHER ++ ++%type options ++ ++%start file ++ ++%% ++ ++file: { ++#if YYDEBUG != 0 ++ amd_debug = YYDEBUG; ++#endif ++ memset(opts, 0, sizeof(opts)); ++ } line ++ ; ++ ++line: ++ | location_selection_list ++ ; ++ ++location_selection_list: location ++ { ++ if (!add_location()) { ++ amd_msg("failed to allocate new location"); ++ YYABORT; ++ } ++ } ++ | location_selection_list SPACE location ++ { ++ if (!add_location()) { ++ amd_msg("failed to allocate new location"); ++ YYABORT; ++ } ++ } ++ | location_selection_list SPACE CUT SPACE location ++ { ++ entry.flags |= AMD_ENTRY_CUT; ++ if (!add_location()) { ++ amd_msg("failed to allocate new location"); ++ YYABORT; ++ } ++ } ++ ; ++ ++location: location_entry ++ { ++ } ++ | HYPHEN location_entry ++ { ++ entry.flags |= AMD_DEFAULTS_MERGE; ++ } ++ | HYPHEN ++ { ++ entry.flags |= AMD_DEFAULTS_RESET; ++ } ++ ; ++ ++location_entry: selector_or_option ++ { ++ } ++ | location_entry SEPERATOR selector_or_option ++ { ++ } ++ | location_entry SEPERATOR ++ { ++ } ++ ; ++ ++selector_or_option: selection ++ { ++ } ++ | option_assignment ++ { ++ } ++ | OTHER ++ { ++ amd_notify($1); ++ YYABORT; ++ } ++ ; ++ ++selection: SELECTOR IS_EQUAL SELECTOR_VALUE ++ { ++ if (!make_selector($1, $3, NULL, SEL_TYPE_EQUAL)) { ++ amd_notify($1); ++ YYABORT; ++ } ++ } ++ | SELECTOR NOT_EQUAL SELECTOR_VALUE ++ { ++ if (!make_selector($1, $3, NULL, SEL_TYPE_NOTEQUAL)) { ++ amd_notify($1); ++ YYABORT; ++ } ++ } ++ ; ++ ++option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE ++ { ++ if (!strcmp($3, "auto")) { ++ entry.flags |= AMD_MOUNT_TYPE_AUTO; ++ entry.type = amd_strdup($3); ++ } else if (!strcmp($3, "nfs") || ++ !strcmp($3, "nfs4")) { ++ entry.flags |= AMD_MOUNT_TYPE_NFS; ++ entry.type = amd_strdup($3); ++ } else if (!strcmp($3, "link")) { ++ entry.flags |= AMD_MOUNT_TYPE_LINK; ++ entry.type = amd_strdup($3); ++ } else if (!strcmp($3, "host")) { ++ entry.flags |= AMD_MOUNT_TYPE_HOST; ++ entry.type = amd_strdup($3); ++ } else { ++ amd_notify($1); ++ YYABORT; ++ } ++ } ++ | MAP_OPTION OPTION_ASSIGN MAP_TYPE ++ { ++ if (!strcmp($3, "file") || ++ !strcmp($3, "nis") || ++ !strcmp($3, "nisplus") || ++ !strcmp($3, "ldap") || ++ !strcmp($3, "hesiod")) ++ entry.map_type = amd_strdup($3); ++ else if (!strcmp($3, "exec")) ++ /* autofs uses "program" for "exec" map type */ ++ entry.map_type = amd_strdup("program"); ++ else { ++ amd_notify($1); ++ YYABORT; ++ } ++ } ++ | MAP_OPTION OPTION_ASSIGN FS_OPT_VALUE ++ { ++ if (!strcmp($1, "fs")) ++ entry.fs = amd_strdup($3); ++ else if (!strcmp($1, "sublink")) ++ entry.sublink = amd_strdup($3); ++ else if (!strcmp($1, "pref")) { ++ if (!strcmp($3, "null")) ++ entry.pref = amd_strdup(""); ++ else ++ entry.pref = amd_strdup($3); ++ } else { ++ amd_notify($1); ++ YYABORT; ++ } ++ } ++ | FS_OPTION OPTION_ASSIGN FS_OPT_VALUE ++ { ++ if (!strcmp($1, "rhost")) ++ entry.rhost = amd_strdup($3); ++ else if (!strcmp($1, "rfs")) ++ entry.rfs = amd_strdup($3); ++ else { ++ amd_notify($1); ++ YYABORT; ++ } ++ } ++ | MNT_OPTION OPTION_ASSIGN options ++ { ++ if (!strcmp($1, "opts")) { ++ entry.opts = amd_strdup(opts); ++ memset(opts, 0, sizeof(opts)); ++ } else if (!strcmp($1, "addopts")) { ++ entry.addopts = amd_strdup(opts); ++ memset(opts, 0, sizeof(opts)); ++ } else if (!strcmp($1, "remopts")) { ++ entry.remopts = amd_strdup(opts); ++ memset(opts, 0, sizeof(opts)); ++ } else { ++ memset(opts, 0, sizeof(opts)); ++ amd_notify($1); ++ YYABORT; ++ } ++ } ++ ; ++ ++options: OPTION ++ { ++ prepend_opt(opts, $1); ++ } ++ | OPTION COMMA options ++ { ++ prepend_opt(opts, $1); ++ } ++ ; ++ ++%% ++ ++static void prepend_opt(char *dest, char *opt) ++{ ++ char new[MAX_OPTS_LEN]; ++ strcpy(new, opt); ++ if (*dest != '\0') { ++ strcat(new, ","); ++ strcat(new, dest); ++ } ++ memmove(dest, new, strlen(new)); ++} ++ ++#if YYDEBUG ++static int amd_fprintf(FILE *f, char *msg, ...) ++{ ++ va_list ap; ++ va_start(ap, msg); ++ vsyslog(LOG_DEBUG, msg, ap); ++ va_end(ap); ++ return 1; ++} ++#endif ++ ++static char *amd_strdup(char *str) ++{ ++ char *tmp; ++ ++ tmp = strdup(str); ++ if (!tmp) ++ amd_error("memory allocation error"); ++ return tmp; ++} ++ ++static int amd_error(const char *s) ++{ ++ if (strcmp(s, "syntax")) ++ logmsg("syntax error in location near [ %s ]\n", amd_text); ++ else ++ logmsg("%s while parsing location.\n", s); ++ return 0; ++} ++ ++static int amd_notify(const char *s) ++{ ++ logmsg("syntax error in location near [ %s ]\n", s); ++ return(0); ++} ++ ++static int amd_msg(const char *s) ++{ ++ logmsg("%s\n", s); ++ return 0; ++} ++ ++static void local_init_vars(void) ++{ ++ memset(&entry, 0, sizeof(entry)); ++ memset(opts, 0, sizeof(opts)); ++} ++ ++static void local_free_vars(void) ++{ ++ clear_amd_entry(&entry); ++ return; ++} ++ ++static void add_selector(struct selector *selector) ++{ ++ struct selector *s = entry.selector; ++ ++ if (!s) { ++ entry.selector = selector; ++ return; ++ } ++ ++ while (s->next) ++ s = s->next; ++ ++ selector->next = s; ++ entry.selector = selector; ++ ++ return; ++} ++ ++static int make_selector(char *name, ++ char *value1, char *value2, ++ unsigned int compare) ++{ ++ struct selector *s; ++ char *tmp; ++ ++ if (!sel_lookup(name)) ++ return 0; ++ ++ if (!value1) ++ return 0; ++ ++ s = get_selector(name); ++ if (!s) ++ return 0; ++ ++ if (s->sel->flags & SEL_FLAG_MACRO) { ++ tmp = amd_strdup(value1); ++ if (!tmp) ++ goto error; ++ s->comp.value = tmp; ++ } else if (s->sel->flags & SEL_FLAG_FUNC1) { ++ char *tmp = amd_strdup(value1); ++ if (!tmp) ++ goto error; ++ s->func.arg1 = tmp; ++ } else if (s->sel->flags & SEL_FLAG_FUNC2) { ++ char *tmp = amd_strdup(value1); ++ if (!tmp) ++ goto error; ++ s->func.arg1 = tmp; ++ if (value2) { ++ tmp = amd_strdup(value2); ++ if (tmp) ++ s->func.arg2 = tmp; ++ } ++ } ++ s->compare = compare; ++ ++ add_selector(s); ++ ++ return 1; ++error: ++ free_selector(s); ++ return 0; ++} ++ ++void amd_init_scan(void) ++{ ++} ++ ++static void parse_mutex_lock(void) ++{ ++ int status = pthread_mutex_lock(&parse_mutex); ++ if (status) ++ fatal(status); ++ return; ++} ++ ++static void parse_mutex_unlock(void *arg) ++{ ++ int status = pthread_mutex_unlock(&parse_mutex); ++ if (status) ++ fatal(status); ++ return; ++} ++ ++static int add_location(void) ++{ ++ struct amd_entry *new; ++ ++ new = new_amd_entry(psv); ++ if (!new) ++ return 0; ++ ++ if (entry.path) { ++ free(new->path); ++ new->path = entry.path; ++ } ++ new->flags = entry.flags; ++ new->type = entry.type; ++ new->map_type = entry.map_type; ++ new->pref = entry.pref; ++ new->fs = entry.fs; ++ new->rhost = entry.rhost; ++ new->rfs = entry.rfs; ++ new->dev = entry.dev; ++ new->opts = entry.opts; ++ new->addopts = entry.addopts; ++ new->remopts = entry.remopts; ++ new->sublink = entry.sublink; ++ new->selector = entry.selector; ++ list_add_tail(&new->list, entries); ++ memset(&entry, 0, sizeof(struct amd_entry)); ++ ++ return 1; ++} ++ ++int amd_parse_list(struct autofs_point *ap, ++ const char *buffer, struct list_head *list, ++ struct substvar **sv) ++{ ++ char *buf; ++ size_t len; ++ int ret; ++ ++ len = strlen(buffer) + 2; ++ buf = malloc(len); ++ if (!buf) ++ return 0; ++ strcpy(buf, buffer); ++ ++ parse_mutex_lock(); ++ pthread_cleanup_push(parse_mutex_unlock, NULL); ++ ++ pap = ap; ++ psv = *sv; ++ entries = list; ++ amd_set_scan_buffer(buf); ++ ++ local_init_vars(); ++ ret = amd_parse(); ++ local_free_vars(); ++ *sv = psv; ++ ++ pthread_cleanup_pop(1); ++ free(buf); ++ ++ return ret; ++} +--- /dev/null ++++ autofs-5.0.7/modules/amd_tok.l +@@ -0,0 +1,316 @@ ++%{ ++/* ----------------------------------------------------------------------- * ++ * ++ * Copyright 2013 Ian Kent ++ * Copyright 2013 Red Hat, Inc. ++ * All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, ++ * USA; either version 2 of the License, or (at your option) any later ++ * version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++#ifdef ECHO ++# undef ECHO ++#endif ++static void amd_echo(void); /* forward definition */ ++#define ECHO amd_echo() ++int amd_wrap(void); ++ ++#include ++#include ++#include ++#include ++#include "amd_parse.tab.h" ++ ++int amd_lex(void); ++int mad_wrap(void); ++ ++#define YY_SKIP_YYWRAP ++ ++#ifndef YY_STACK_USED ++#define YY_STACK_USED 0 ++#endif ++#ifndef YY_ALWAYS_INTERACTIVE ++#define YY_ALWAYS_INTERACTIVE 0 ++#endif ++#ifndef YY_NEVER_INTERACTIVE ++#define YY_NEVER_INTERACTIVE 0 ++#endif ++#ifndef YY_MAIN ++#define YY_MAIN 0 ++#endif ++ ++void amd_set_scan_buffer(const char *); ++static const char *line = NULL; ++ ++#ifdef FLEX_SCANNER ++static const char *line_pos = NULL; ++static const char *line_lim = NULL; ++int amd_yyinput(char *, int); ++ ++#undef YY_INPUT ++#define YY_INPUT(b, r, ms) (r = amd_yyinput(b, ms)) ++#else ++#undef input ++#undef unput ++#define input() (*(char *) line++) ++#define unput(c) (*(char *) --line = c) ++#endif ++ ++%} ++ ++%option nounput ++ ++%x MAPOPTVAL FSOPTVAL MNTOPTVAL SELOPTVAL ++ ++NL \r?\n ++OPTWS [[:blank:]]* ++OTHR [^!;:=/|\- \t\r\n#]* ++ ++MACRO (\$\{([[:alpha:]_/]([[:alnum:]_\-])([[:alnum:]_\-/])*)\}) ++QSTR (\"([^"\\]|\\.)*\") ++OSTR ([[:alpha:]]([[:alnum:]_\-])+) ++FSTR ([[:alnum:]_/\.]([[:alnum:]_\-/\.]|(\\.))*) ++VSTR (([[:alnum:]_\-\:/\.])+) ++SSTR ([[:alpha:]]([[:alnum:]\-\.])+) ++ ++FOPT (({QSTR}|{FSTR}|{MACRO})+) ++OPTS ({OSTR}(=({VSTR}|{QSTR}|{MACRO})+)?) ++SOPT (({SSTR}|{QSTR}|{MACRO})+) ++ ++MAPOPT (fs|type|maptype|pref|sublink|delay) ++MNTOPT (opts|addopts|remopts) ++FSOPTS (rhost|rfs|dev|cachedir) ++MAPTYPE (file|nis|nisplus|ldap|hesiod|exec|ndbm|passwd|union) ++FSTYPE (auto|nfs|link|host|nfsx|ufs|xfs|efs) ++ ++OSSEL (arch|karch|os|osver|full_os|vendor) ++HSTSEL (host|hostd|xhost|domain|byte|cluster) ++NETSEL (netnumber|network|wire|netgrp|netgrpd|in_network) ++USRSEL (uid|gid) ++MAPSEL (key|map|path) ++OTRSEL (exists|autodir|dollar) ++BOLSEL (true|false) ++SELOPT ({OSSEL}|{HSTSEL}|{NETSEL}|{BOLSEL}|{USRSEL}|{MAPSEL}|{OTRSEL}) ++ ++CUTSEP (\|\||\/) ++ ++%% ++ ++{ ++ {NL} | ++ \x00 { } ++ ++ {MAPOPT} { ++ BEGIN(MAPOPTVAL); ++ strcpy(amd_lval.strtype, amd_text); ++ return MAP_OPTION; ++ ++ } ++ ++ {FSOPTS} { ++ BEGIN(FSOPTVAL); ++ strcpy(amd_lval.strtype, amd_text); ++ return FS_OPTION; ++ } ++ ++ {MNTOPT} { ++ BEGIN(MNTOPTVAL); ++ strcpy(amd_lval.strtype, amd_text); ++ return MNT_OPTION; ++ } ++ ++ {SELOPT} { ++ BEGIN(SELOPTVAL); ++ strcpy(amd_lval.strtype, amd_text); ++ return SELECTOR; ++ } ++ ++ {CUTSEP} { return CUT; } ++ ++ "-" { return HYPHEN; } ++ ++ {OPTWS} { return SPACE; } ++ ++ #.* { return COMMENT; } ++ ++ {OTHR} { ++ strcpy(amd_lval.strtype, amd_text); ++ return OTHER; ++ } ++} ++ ++{ ++ {NL} | ++ \x00 { ++ BEGIN(INITIAL); ++ yyless(1); ++ } ++ ++ ";" { ++ BEGIN(INITIAL); ++ return SEPERATOR; ++ } ++ ++ {OPTWS} { ++ BEGIN(INITIAL); ++ return SPACE; ++ } ++ ++ ":=" { return OPTION_ASSIGN; } ++ ++ {FSTYPE} { ++ strcpy(amd_lval.strtype, amd_text); ++ return FS_TYPE; ++ } ++ ++ {MAPTYPE} { ++ strcpy(amd_lval.strtype, amd_text); ++ return MAP_TYPE; ++ } ++ ++ {FOPT} { ++ strcpy(amd_lval.strtype, amd_text); ++ return FS_OPT_VALUE; ++ } ++} ++ ++{ ++ {NL} | ++ \x00 { ++ BEGIN(INITIAL); ++ yyless(1); ++ } ++ ++ ";" { ++ BEGIN(INITIAL); ++ return SEPERATOR; ++ } ++ ++ {OPTWS} { ++ BEGIN(INITIAL); ++ return SPACE; ++ } ++ ++ ":=" { return OPTION_ASSIGN; } ++ ++ {FOPT} { ++ strcpy(amd_lval.strtype, amd_text); ++ return FS_OPT_VALUE; ++ } ++} ++ ++{ ++ {NL} | ++ \x00 { ++ BEGIN(INITIAL); ++ yyless(1); ++ } ++ ++ ";" { ++ BEGIN(INITIAL); ++ return SEPERATOR; ++ } ++ ++ {OPTWS} { ++ BEGIN(INITIAL); ++ return SPACE; ++ } ++ ++ ":=" { return OPTION_ASSIGN; } ++ ++ "," { return COMMA; } ++ ++ {OPTS} { ++ strcpy(amd_lval.strtype, amd_text); ++ return OPTION; ++ } ++} ++ ++{ ++ {NL} | ++ \x00 { ++ BEGIN(INITIAL); ++ yyless(1); ++ } ++ ++ ";" { ++ BEGIN(INITIAL); ++ return SEPERATOR; ++ } ++ ++ {OPTWS} { ++ BEGIN(INITIAL); ++ return SPACE; ++ } ++ ++ "==" { return IS_EQUAL; } ++ ++ "!=" { return NOT_EQUAL; } ++ ++ {SOPT} { ++ strcpy(amd_lval.strtype, amd_text); ++ return SELECTOR_VALUE; ++ } ++} ++ ++%% ++ ++#include "automount.h" ++ ++int amd_wrap(void) ++{ ++ return 1; ++} ++ ++static void amd_echo(void) ++{ ++ logmsg("%s\n", amd_text); ++ return; ++} ++ ++#ifdef FLEX_SCANNER ++ ++void amd_set_scan_buffer(const char *buffer) ++{ ++ line = buffer; ++ line_pos = &line[0]; ++ /* ++ * Ensure buffer is 1 greater than string and is zeroed before ++ * the parse so we can fit the extra NULL which allows us to ++ * explicitly match an end of line within the buffer (ie. the ++ * need for 2 NULLS when parsing in memeory buffers). ++ */ ++ line_lim = line + strlen(buffer) + 1; ++} ++ ++#define amd_min(a,b) (((a) < (b)) ? (a) : (b)) ++ ++int amd_yyinput(char *buffer, int max_size) ++{ ++ int n = amd_min(max_size, line_lim - line_pos); ++ ++ if (n > 0) { ++ memcpy(buffer, line_pos, n); ++ line_pos += n; ++ } ++ return n; ++} ++ ++#else ++ ++void amd_set_scan_buffer(const char *buffer) ++{ ++ line = buffer; ++} ++ ++#endif +--- /dev/null ++++ autofs-5.0.7/modules/parse_amd.c +@@ -0,0 +1,1081 @@ ++/* ----------------------------------------------------------------------- * ++ * ++ * Copyright 2013 Ian Kent ++ * Copyright 2013 Red Hat, Inc. ++ * All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, ++ * USA; either version 2 of the License, or (at your option) any later ++ * version; incorporated herein by reference. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_PARSE ++#include "automount.h" ++ ++#define MODPREFIX "parse(amd): " ++ ++int parse_version = AUTOFS_PARSE_VERSION; /* Required by protocol */ ++ ++static struct mount_mod *mount_nfs = NULL; ++static int init_ctr = 0; ++static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++static void instance_mutex_lock(void) ++{ ++ int status = pthread_mutex_lock(&instance_mutex); ++ if (status) ++ fatal(status); ++} ++ ++static void instance_mutex_unlock(void) ++{ ++ int status = pthread_mutex_unlock(&instance_mutex); ++ if (status) ++ fatal(status); ++} ++ ++extern const char *global_options; ++ ++struct parse_context { ++ char *optstr; /* Mount options */ ++ char *macros; /* Map wide macro defines */ ++ struct substvar *subst; /* $-substitutions */ ++}; ++ ++struct multi_mnt { ++ char *path; ++ char *options; ++ char *location; ++ struct multi_mnt *next; ++}; ++ ++/* Default context */ ++ ++static struct parse_context default_context = { ++ NULL, /* No mount options */ ++ NULL, /* No map wide macros */ ++ NULL /* The substvar local vars table */ ++}; ++ ++/* Free all storage associated with this context */ ++static void kill_context(struct parse_context *ctxt) ++{ ++ macro_lock(); ++ macro_free_table(ctxt->subst); ++ macro_unlock(); ++ if (ctxt->optstr) ++ free(ctxt->optstr); ++ if (ctxt->macros) ++ free(ctxt->macros); ++ free(ctxt); ++} ++ ++int parse_init(int argc, const char *const *argv, void **context) ++{ ++ struct parse_context *ctxt; ++ char buf[MAX_ERR_BUF]; ++ ++ sel_hash_init(); ++ ++ /* Set up context and escape chain */ ++ ++ if (!(ctxt = (struct parse_context *) malloc(sizeof(struct parse_context)))) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ logerr(MODPREFIX "malloc: %s", estr); ++ *context = NULL; ++ return 1; ++ } ++ *context = (void *) ctxt; ++ ++ *ctxt = default_context; ++ ++ /* We only need this once. NFS mounts are so common that we cache ++ this module. */ ++ instance_mutex_lock(); ++ if (mount_nfs) ++ init_ctr++; ++ else { ++ if ((mount_nfs = open_mount("nfs", MODPREFIX))) { ++ init_ctr++; ++ } else { ++ kill_context(ctxt); ++ *context = NULL; ++ instance_mutex_unlock(); ++ return 1; ++ } ++ } ++ instance_mutex_unlock(); ++ ++ return 0; ++} ++ ++static void update_with_defaults(struct amd_entry *defaults, ++ struct amd_entry *entry, ++ struct substvar *sv) ++{ ++ const struct substvar *v; ++ unsigned long fstype = entry->flags & AMD_MOUNT_TYPE_MASK; ++ char *tmp; ++ ++ if (fstype == AMD_MOUNT_TYPE_NONE) { ++ unsigned long deftype = defaults->flags & AMD_MOUNT_TYPE_MASK; ++ if (deftype != AMD_MOUNT_TYPE_NONE) ++ entry->flags |= (defaults->flags & AMD_MOUNT_TYPE_MASK); ++ else { ++ entry->flags = AMD_MOUNT_TYPE_NFS; ++ tmp = strdup("nfs"); ++ if (tmp) ++ entry->type = tmp; ++ } ++ } ++ ++ if (!entry->type && defaults->type) { ++ tmp = strdup(defaults->type); ++ if (tmp) ++ entry->type = tmp; ++ } ++ ++ if (!entry->map_type && defaults->map_type) { ++ tmp = strdup(defaults->map_type); ++ if (tmp) ++ entry->map_type = tmp; ++ } ++ ++ if (!entry->pref && defaults->pref) { ++ tmp = strdup(defaults->pref); ++ if (tmp) ++ entry->pref = tmp; ++ } ++ ++ if (!entry->fs && defaults->fs) { ++ tmp = strdup(defaults->fs); ++ if (tmp) ++ entry->fs = tmp; ++ } ++ ++ if (!entry->rfs && defaults->rfs) { ++ tmp = strdup(defaults->rfs); ++ if (tmp) ++ entry->rfs = tmp; ++ } ++ ++ if (!entry->rhost && defaults->rhost) { ++ tmp = strdup(defaults->rhost); ++ if (tmp) ++ entry->rhost = tmp; ++ } ++ ++ if (!entry->opts && defaults->opts) { ++ tmp = merge_options(defaults->opts, entry->opts); ++ if (tmp) ++ entry->opts = tmp; ++ } ++ ++ if (!entry->addopts && defaults->addopts) { ++ tmp = merge_options(defaults->addopts, entry->addopts); ++ if (tmp) ++ entry->addopts = tmp; ++ } ++ ++ if (!entry->remopts && defaults->remopts) { ++ tmp = merge_options(defaults->remopts, entry->remopts); ++ if (tmp) ++ entry->remopts = tmp; ++ } ++ ++ return; ++} ++ ++static char *normalize_hostname(unsigned int logopt, const char *host, ++ unsigned int flags, struct substvar *sv) ++{ ++ struct addrinfo hints, *ni; ++ char *name; ++ int ret; ++ ++ if (!(flags & CONF_NORMALIZE_HOSTNAMES)) ++ name = strdup(host); ++ else { ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_flags = AI_CANONNAME; ++ hints.ai_family = AF_UNSPEC; ++ hints.ai_socktype = SOCK_DGRAM; ++ ++ ret = getaddrinfo(host, NULL, &hints, &ni); ++ if (ret) { ++ error(logopt, "hostname lookup failed: %s", gai_strerror(ret)); ++ return NULL; ++ } ++ name = strdup(ni->ai_canonname); ++ freeaddrinfo(ni); ++ } ++ ++ if (!name) ++ return NULL; ++ ++ if (flags & CONF_DOMAIN_STRIP) { ++ const struct substvar *v = macro_findvar(sv, "hostd", 5); ++ if (v) { ++ char *d1 = strchr(name, '.'); ++ if (d1) { ++ char *d2 = strchr(v->val, '.'); ++ if (d2 && !strcmp(d1, d2)) ++ *d1 = '\0'; ++ } ++ } ++ } ++ ++ return name; ++} ++ ++static struct substvar *expand_entry(struct autofs_point *ap, ++ struct amd_entry *entry, ++ unsigned int flags, ++ struct substvar *sv) ++{ ++ unsigned int logopt = ap->logopt; ++ char *expand; ++ ++ if (entry->rhost) { ++ char *host = strdup(entry->rhost); ++ char *nn; ++ if (!host) { ++ error(ap->logopt, MODPREFIX ++ "failed to allocate storage for rhost"); ++ goto next; ++ } ++ if (expand_selectors(ap, host, &expand, sv)) { ++ free(host); ++ host = expand; ++ } ++ nn = normalize_hostname(ap->logopt, host, flags, sv); ++ if (!nn) ++ sv = macro_addvar(sv, "rhost", 5, host); ++ else { ++ sv = macro_addvar(sv, "rhost", 5, nn); ++ free(host); ++ host = nn; ++ } ++ debug(logopt, MODPREFIX ++ "rhost expand(\"%s\") -> %s", entry->rhost, host); ++ free(entry->rhost); ++ entry->rhost = host; ++ } ++next: ++ if (entry->sublink) { ++ if (expand_selectors(ap, entry->sublink, &expand, sv)) { ++ debug(logopt, MODPREFIX ++ "sublink expand(\"%s\") -> %s", ++ entry->sublink, expand); ++ free(entry->sublink); ++ entry->sublink = expand; ++ } ++ sv = macro_addvar(sv, "sublink", 7, entry->sublink); ++ } ++ ++ if (entry->rfs) { ++ if (expand_selectors(ap, entry->rfs, &expand, sv)) { ++ debug(logopt, MODPREFIX ++ "rfs expand(\"%s\") -> %s", entry->rfs, expand); ++ free(entry->rfs); ++ entry->rfs = expand; ++ } ++ sv = macro_addvar(sv, "rfs", 3, entry->rfs); ++ } ++ ++ if (entry->fs) { ++ if (expand_selectors(ap, entry->fs, &expand, sv)) { ++ debug(logopt, MODPREFIX ++ "fs expand(\"%s\") -> %s", entry->fs, expand); ++ free(entry->fs); ++ entry->fs = expand; ++ } ++ sv = macro_addvar(sv, "fs", 2, entry->fs); ++ } ++ ++ if (entry->opts) { ++ if (expand_selectors(ap, entry->opts, &expand, sv)) { ++ debug(logopt, MODPREFIX ++ "ops expand(\"%s\") -> %s", entry->opts, expand); ++ free(entry->opts); ++ entry->opts = expand; ++ } ++ sv = macro_addvar(sv, "opts", 4, entry->opts); ++ } ++ ++ if (entry->addopts) { ++ if (expand_selectors(ap, entry->addopts, &expand, sv)) { ++ debug(logopt, MODPREFIX ++ "addopts expand(\"%s\") -> %s", ++ entry->addopts, expand); ++ free(entry->addopts); ++ entry->addopts = expand; ++ } ++ sv = macro_addvar(sv, "addopts", 7, entry->addopts); ++ } ++ ++ if (entry->remopts) { ++ if (expand_selectors(ap, entry->remopts, &expand, sv)) { ++ debug(logopt, MODPREFIX ++ "remopts expand(\"%s\") -> %s", ++ entry->remopts, expand); ++ free(entry->remopts); ++ entry->remopts = expand; ++ } ++ sv = macro_addvar(sv, "remopts", 7, entry->remopts); ++ } ++ ++ return sv; ++} ++ ++static void expand_merge_options(struct autofs_point *ap, ++ struct amd_entry *entry, ++ struct substvar *sv) ++{ ++ char *tmp; ++ ++ if (entry->opts) { ++ if (!expand_selectors(ap, entry->opts, &tmp, sv)) ++ error(ap->logopt, MODPREFIX "failed to expand opts"); ++ else { ++ free(entry->opts); ++ entry->opts = tmp; ++ } ++ } ++ ++ if (entry->addopts) { ++ if (!expand_selectors(ap, entry->addopts, &tmp, sv)) ++ error(ap->logopt, MODPREFIX "failed to expand addopts"); ++ else { ++ free(entry->addopts); ++ entry->addopts = tmp; ++ } ++ } ++ ++ if (entry->remopts) { ++ if (!expand_selectors(ap, entry->remopts, &tmp, sv)) ++ error(ap->logopt, MODPREFIX "failed to expand remopts"); ++ else { ++ free(entry->remopts); ++ entry->remopts = tmp; ++ } ++ } ++ ++ return; ++} ++ ++static struct substvar *merge_entry_options(struct autofs_point *ap, ++ struct amd_entry *entry, ++ struct substvar *sv) ++{ ++ char *tmp; ++ ++ if (!entry->addopts) ++ return sv; ++ ++ if (entry->opts && entry->remopts && ++ !strcmp(entry->opts, entry->remopts)) { ++ expand_merge_options(ap, entry, sv); ++ tmp = merge_options(entry->opts, entry->addopts); ++ if (tmp) { ++ info(ap->logopt, MODPREFIX ++ "merge remopts \"%s\" addopts \"%s\" => \"%s\"", ++ entry->opts, entry->addopts, tmp); ++ free(entry->opts); ++ entry->opts = tmp; ++ sv = macro_addvar(sv, "opts", 4, entry->opts); ++ } ++ tmp = strdup(entry->opts); ++ if (tmp) { ++ free(entry->remopts); ++ entry->remopts = tmp; ++ sv = macro_addvar(sv, "remopts", 7, entry->remopts); ++ } ++ return sv; ++ } ++ ++ expand_merge_options(ap, entry, sv); ++ ++ if (entry->opts && entry->addopts) { ++ tmp = merge_options(entry->opts, entry->addopts); ++ if (tmp) { ++ info(ap->logopt, MODPREFIX ++ "merge opts \"%s\" addopts \"%s\" => \"%s\"", ++ entry->opts, entry->addopts, tmp); ++ free(entry->opts); ++ entry->opts = tmp; ++ sv = macro_addvar(sv, "opts", 4, entry->opts); ++ } ++ } else if (entry->addopts) { ++ tmp = strdup(entry->addopts); ++ if (tmp) { ++ info(ap->logopt, MODPREFIX ++ "opts add addopts \"%s\" => \"%s\"", entry->addopts, tmp); ++ entry->opts = tmp; ++ sv = macro_addvar(sv, "opts", 4, entry->opts); ++ } ++ } ++ ++ expand_merge_options(ap, entry, sv); ++ ++ if (entry->remopts && entry->addopts) { ++ tmp = merge_options(entry->remopts, entry->addopts); ++ if (tmp) { ++ info(ap->logopt, MODPREFIX ++ "merge remopts \"%s\" addopts \"%s\" => \"%s\"", ++ entry->remopts, entry->addopts, tmp); ++ free(entry->remopts); ++ entry->remopts = tmp; ++ sv = macro_addvar(sv, "remopts", 7, entry->remopts); ++ } ++ } else if (entry->addopts) { ++ tmp = strdup(entry->addopts); ++ if (tmp) { ++ info(ap->logopt, MODPREFIX ++ "remopts add addopts \"%s\" => \"%s\"", ++ entry->addopts, tmp); ++ entry->remopts = tmp; ++ sv = macro_addvar(sv, "remopts", 7, entry->remopts); ++ } ++ } ++ ++ return sv; ++} ++ ++static int do_auto_mount(struct autofs_point *ap, const char *name, ++ struct amd_entry *entry, unsigned int flags) ++{ ++ char target[PATH_MAX + 1]; ++ int ret; ++ ++ if (!entry->map_type) ++ strcpy(target, entry->fs); ++ else { ++ strcpy(target, entry->map_type); ++ strcat(target, ",amd:"); ++ strcat(target, entry->fs); ++ } ++ ++ ret = do_mount(ap, ap->path, ++ name, strlen(name), target, "autofs", NULL); ++ if (!ret) { ++ struct autofs_point *sm; ++ sm = master_find_submount(ap, entry->path); ++ if (sm) { ++ sm->pref = entry->pref; ++ entry->pref = NULL; ++ } ++ } ++ ++ return ret; ++} ++ ++static int do_link_mount(struct autofs_point *ap, const char *name, ++ struct amd_entry *entry, unsigned int flags) ++{ ++ char target[PATH_MAX + 1]; ++ int ret; ++ ++ if (entry->sublink) ++ strcpy(target, entry->sublink); ++ else ++ strcpy(target, entry->fs); ++ ++ if (!(flags & CONF_AUTOFS_USE_LOFS)) ++ goto symlink; ++ ++ /* For a sublink this might cause an external mount */ ++ ret = do_mount(ap, ap->path, ++ name, strlen(name), target, "bind", entry->opts); ++ if (!ret) ++ goto out; ++ ++ debug(ap->logopt, MODPREFIX "bind mount failed, symlinking"); ++ ++symlink: ++ ret = do_mount(ap, ap->path, ++ name, strlen(name), target, "bind", "symlink"); ++ if (!ret) ++ goto out; ++ ++ error(ap->logopt, MODPREFIX ++ "failed to symlink %s to %s", entry->path, target); ++ ++ if (entry->sublink) { ++ /* failed to complete sublink mount */ ++ if (ext_mount_remove(&entry->ext_mount, entry->fs)) ++ umount_ent(ap, entry->fs); ++ } ++out: ++ return ret; ++} ++ ++static int do_nfs_mount(struct autofs_point *ap, const char *name, ++ struct amd_entry *entry, unsigned int flags) ++{ ++ char target[PATH_MAX + 1]; ++ int ret = 0; ++ ++ strcpy(target, entry->rhost); ++ strcat(target, ":"); ++ strcat(target, entry->rfs); ++ ++ if (!entry->sublink) { ++ ret = mount_nfs->mount_mount(ap, ap->path, name, strlen(name), ++ target, entry->type, entry->opts, ++ mount_nfs->context); ++ } else { ++ if (!is_mounted(_PATH_MOUNTED, entry->fs, MNTS_REAL)) { ++ ret = mount_nfs->mount_mount(ap, entry->fs, "/", 1, ++ target, entry->type, entry->opts, ++ mount_nfs->context); ++ if (ret) ++ goto out; ++ } ++ /* We might be using an external mount */ ++ ext_mount_add(&entry->ext_mount, entry->fs); ++ ret = do_link_mount(ap, name, entry, flags); ++ } ++out: ++ return ret; ++} ++ ++static int do_host_mount(struct autofs_point *ap, const char *name, ++ struct amd_entry *entry, struct map_source *source, ++ unsigned int flags) ++{ ++ struct lookup_mod *lookup; ++ struct mapent *me; ++ const char *argv[2]; ++ int ret = 1; ++ ++ argv[0] = entry->opts; ++ argv[1] = NULL; ++ ++ lookup = open_lookup("hosts", MODPREFIX, NULL, 1, argv); ++ if (!lookup) { ++ debug(ap->logopt, "open lookup module hosts failed"); ++ goto out; ++ } ++ ++ me = cache_lookup_distinct(source->mc, name); ++ if (me) ++ cache_push_mapent(me, NULL); ++ ++ master_source_current_wait(ap->entry); ++ ap->entry->current = source; ++ ++ ret = lookup->lookup_mount(ap, name, strlen(name), lookup->context); ++ ++ close_lookup(lookup); ++out: ++ return ret; ++} ++ ++static int amd_mount(struct autofs_point *ap, const char *name, ++ struct amd_entry *entry, struct map_source *source, ++ struct substvar *sv, unsigned int flags, ++ struct parse_context *ctxt) ++{ ++ unsigned long fstype = entry->flags & AMD_MOUNT_TYPE_MASK; ++ int ret = 1; ++ ++ switch (fstype) { ++ case AMD_MOUNT_TYPE_AUTO: ++ ret = do_auto_mount(ap, name, entry, flags); ++ break; ++ ++ case AMD_MOUNT_TYPE_NFS: ++ ret = do_nfs_mount(ap, name, entry, flags); ++ break; ++ ++ case AMD_MOUNT_TYPE_LINK: ++ ret = do_link_mount(ap, name, entry, flags); ++ break; ++ ++ case AMD_MOUNT_TYPE_HOST: ++ ret = do_host_mount(ap, name, entry, source, flags); ++ break; ++ ++ default: ++ info(ap->logopt, ++ MODPREFIX "unkown file system type %x", fstype); ++ break; ++ } ++ ++ return ret; ++} ++ ++void dequote_entry(struct autofs_point *ap, struct amd_entry *entry) ++{ ++ char *res; ++ ++ if (entry->pref) { ++ res = dequote(entry->pref, strlen(entry->pref), ap->logopt); ++ if (res) { ++ debug(ap->logopt, ++ MODPREFIX "pref dequote(\"%.*s\") -> %s", ++ strlen(entry->pref), entry->pref, res); ++ free(entry->pref); ++ entry->pref = res; ++ } ++ } ++ ++ if (entry->sublink) { ++ res = dequote(entry->sublink, strlen(entry->sublink), ap->logopt); ++ if (res) { ++ debug(ap->logopt, ++ MODPREFIX "sublink dequote(\"%.*s\") -> %s", ++ strlen(entry->sublink), entry->sublink, res); ++ free(entry->sublink); ++ entry->sublink = res; ++ } ++ } ++ ++ if (entry->fs) { ++ res = dequote(entry->fs, strlen(entry->fs), ap->logopt); ++ if (res) { ++ debug(ap->logopt, ++ MODPREFIX "fs dequote(\"%.*s\") -> %s", ++ strlen(entry->fs), entry->fs, res); ++ free(entry->fs); ++ entry->fs = res; ++ } ++ } ++ ++ if (entry->rfs) { ++ res = dequote(entry->rfs, strlen(entry->rfs), ap->logopt); ++ if (res) { ++ debug(ap->logopt, ++ MODPREFIX "rfs dequote(\"%.*s\") -> %s", ++ strlen(entry->rfs), entry->rfs, res); ++ free(entry->rfs); ++ entry->rfs = res; ++ } ++ } ++ ++ if (entry->opts) { ++ res = dequote(entry->opts, strlen(entry->opts), ap->logopt); ++ if (res) { ++ debug(ap->logopt, ++ MODPREFIX "ops dequote(\"%.*s\") -> %s", ++ strlen(entry->opts), entry->opts, res); ++ free(entry->opts); ++ entry->opts = res; ++ } ++ } ++ ++ if (entry->remopts) { ++ res = dequote(entry->remopts, strlen(entry->remopts), ap->logopt); ++ if (res) { ++ debug(ap->logopt, ++ MODPREFIX "remopts dequote(\"%.*s\") -> %s", ++ strlen(entry->remopts), entry->remopts, res); ++ free(entry->remopts); ++ entry->remopts = res; ++ } ++ } ++ ++ if (entry->addopts) { ++ res = dequote(entry->addopts, strlen(entry->addopts), ap->logopt); ++ if (res) { ++ debug(ap->logopt, ++ MODPREFIX "addopts dequote(\"%.*s\") -> %s", ++ strlen(entry->addopts), entry->addopts, res); ++ free(entry->addopts); ++ entry->addopts = res; ++ } ++ } ++ ++ return; ++} ++ ++static void normalize_sublink(unsigned int logopt, ++ struct amd_entry *entry, struct substvar *sv) ++{ ++ char *new; ++ size_t len; ++ ++ if (entry->sublink && *entry->sublink != '/') { ++ len = strlen(entry->fs) + strlen(entry->sublink) + 2; ++ new = malloc(len); ++ if (!new) { ++ error(logopt, MODPREFIX ++ "error: couldn't allocate storage for sublink"); ++ return; ++ } ++ strcpy(new, entry->fs); ++ strcat(new, "/"); ++ strcat(new, entry->sublink); ++ debug(logopt, MODPREFIX ++ "rfs dequote(\"%.*s\") -> %s", ++ strlen(entry->sublink), entry->sublink, new); ++ free(entry->sublink); ++ entry->sublink = new; ++ } ++ return; ++} ++ ++static struct amd_entry *dup_defaults_entry(struct amd_entry *defaults) ++{ ++ struct amd_entry *entry; ++ char *tmp; ++ ++ entry = malloc(sizeof(struct amd_entry)); ++ if (!entry) ++ return NULL; ++ memset(entry, 0, sizeof(struct amd_entry)); ++ ++ entry->flags = defaults->flags; ++ ++ if (defaults->type) { ++ tmp = strdup(defaults->type); ++ if (tmp) ++ entry->type = tmp; ++ } ++ ++ if (defaults->map_type) { ++ tmp = strdup(defaults->map_type); ++ if (tmp) ++ entry->map_type = tmp; ++ } ++ ++ if (defaults->pref) { ++ tmp = strdup(defaults->pref); ++ if (tmp) ++ entry->pref = tmp; ++ } ++ ++ if (defaults->fs) { ++ tmp = strdup(defaults->fs); ++ if (tmp) ++ entry->fs = tmp; ++ } ++ ++ if (defaults->rfs) { ++ tmp = strdup(defaults->rfs); ++ if (tmp) ++ entry->rfs = tmp; ++ } ++ ++ if (defaults->rhost) { ++ tmp = strdup(defaults->rhost); ++ if (tmp) ++ entry->rhost = tmp; ++ } ++ ++ if (defaults->opts) { ++ tmp = strdup(defaults->opts); ++ if (tmp) ++ entry->opts = tmp; ++ } ++ ++ if (defaults->addopts) { ++ tmp = strdup(defaults->addopts); ++ if (tmp) ++ entry->addopts = tmp; ++ } ++ ++ if (defaults->remopts) { ++ tmp = strdup(defaults->remopts); ++ if (tmp) ++ entry->remopts = tmp; ++ } ++ ++ INIT_LIST_HEAD(&entry->list); ++ ++ return entry; ++} ++ ++struct amd_entry *make_default_entry(struct autofs_point *ap, ++ struct substvar *sv) ++{ ++ char *defaults = "opts:=rw,defaults"; ++ struct amd_entry *defaults_entry; ++ struct list_head dflts; ++ ++ INIT_LIST_HEAD(&dflts); ++ if (amd_parse_list(ap, defaults, &dflts, &sv)) ++ return NULL; ++ defaults_entry = list_entry(dflts.next, struct amd_entry, list); ++ list_del_init(&defaults_entry->list); ++ /* The list should now be empty .... */ ++ free_amd_entry_list(&dflts); ++ return defaults_entry; ++} ++ ++static struct amd_entry *select_default_entry(struct autofs_point *ap, ++ struct list_head *entries, ++ struct substvar *sv) ++{ ++ unsigned long flags = conf_amd_get_flags(ap->path); ++ struct amd_entry *defaults_entry = NULL; ++ struct amd_entry *entry_default = NULL; ++ struct list_head *p, *head; ++ ++ if (!(flags & CONF_SELECTORS_IN_DEFAULTS)) ++ goto no_sel; ++ ++ head = entries; ++ p = head->next; ++ while (p != head) { ++ struct amd_entry *this = list_entry(p, struct amd_entry, list); ++ ++ p = p->next; ++ ++ if (this->flags & AMD_DEFAULTS_MERGE) { ++ if (entry_default) ++ free_amd_entry(entry_default); ++ list_del_init(&this->list); ++ entry_default = this; ++ continue; ++ } else if (this->flags & AMD_DEFAULTS_RESET) { ++ struct amd_entry *new; ++ new = dup_defaults_entry(defaults_entry); ++ if (new) { ++ free_amd_entry(entry_default); ++ entry_default = new; ++ } ++ list_del_init(&this->list); ++ free_amd_entry(this); ++ continue; ++ } ++ } ++ ++ /* Not strickly amd semantics but ... */ ++ if (!defaults_entry && entry_default) { ++ defaults_entry = entry_default; ++ goto done; ++ } ++ ++ if (!defaults_entry) { ++ debug(ap->logopt, MODPREFIX ++ "no matching selector(s) found in defaults, " ++ "using internal defaults"); ++ goto ret_default; ++ } ++ ++ goto done; ++ ++no_sel: ++ if (list_empty(entries)) ++ goto ret_default; ++ ++ defaults_entry = list_entry(entries->next, struct amd_entry, list); ++ list_del_init(&defaults_entry->list); ++ if (!list_empty(entries)) { ++ free_amd_entry(defaults_entry); ++ goto ret_default; ++ } ++done: ++ /*merge_entry_options(ap, defaults_entry, sv);*/ ++ /*normalize_sublink(ap->logopt, defaults_entry, sv);*/ ++ return defaults_entry; ++ ++ret_default: ++ return make_default_entry(ap, sv); ++} ++ ++static struct amd_entry *get_defaults_entry(struct autofs_point *ap, ++ const char *defaults, ++ struct substvar *sv) ++{ ++ struct amd_entry *entry; ++ struct list_head dflts; ++ ++ INIT_LIST_HEAD(&dflts); ++ ++ entry = NULL; ++ if (!defaults) ++ goto out; ++ else { ++ char *expand; ++ if (!expand_selectors(ap, defaults, &expand, sv)) ++ goto out; ++ if (amd_parse_list(ap, expand, &dflts, &sv)) ++ goto out; ++ entry = select_default_entry(ap, &dflts, sv); ++ free(expand); ++ } ++ ++ return entry; ++out: ++ return make_default_entry(ap, sv); ++} ++ ++int parse_mount(struct autofs_point *ap, const char *name, ++ int name_len, const char *mapent, void *context) ++{ ++ struct parse_context *ctxt = (struct parse_context *) context; ++ unsigned int flags = conf_amd_get_flags(ap->path); ++ struct substvar *sv = NULL; ++ struct map_source *source; ++ struct mapent_cache *mc; ++ struct mapent *me; ++ struct list_head entries, *p, *head; ++ struct amd_entry *defaults_entry; ++ struct amd_entry *cur_defaults; ++ char *defaults; ++ char *pmapent; ++ int len, rv = 1; ++ int cur_state; ++ int ret; ++ ++ source = ap->entry->current; ++ ap->entry->current = NULL; ++ master_source_current_signal(ap->entry); ++ ++ mc = source->mc; ++ ++ if (!mapent) { ++ warn(ap->logopt, MODPREFIX "error: empty map entry"); ++ return 1; ++ } ++ ++ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); ++ ++ len = expand_selectors(ap, mapent, &pmapent, sv); ++ if (!len) { ++ macro_free_table(sv); ++ pthread_setcancelstate(cur_state, NULL); ++ return 1; ++ } ++ ++ pthread_setcancelstate(cur_state, NULL); ++ ++ debug(ap->logopt, MODPREFIX "expanded mapent: %s", pmapent); ++ ++ defaults = conf_amd_get_map_defaults(ap->path); ++ if (defaults) { ++ debug(ap->logopt, MODPREFIX ++ "using map_defaults %s for %s", defaults, ap->path); ++ } else if ((me = cache_lookup_distinct(mc, "/defaults"))) { ++ defaults = strdup(me->mapent); ++ if (defaults) ++ debug(ap->logopt, MODPREFIX ++ "using /defaults %s from map", defaults); ++ else { ++ char buf[MAX_ERR_BUF]; ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ } ++ } ++ ++ defaults_entry = get_defaults_entry(ap, defaults, sv); ++ if (!defaults_entry) { ++ error(ap->logopt, MODPREFIX "failed to get a defaults entry"); ++ if (defaults) ++ free(defaults); ++ free(pmapent); ++ macro_free_table(sv); ++ return 1; ++ } ++ if (defaults) ++ free(defaults); ++ ++ INIT_LIST_HEAD(&entries); ++ ++ ret = amd_parse_list(ap, pmapent, &entries, &sv); ++ if (ret) { ++ error(ap->logopt, ++ MODPREFIX "failed to parse entry: %s", pmapent); ++ free(pmapent); ++ goto done; ++ } ++ ++ free(pmapent); ++ ++ if (list_empty(&entries)) { ++ error(ap->logopt, MODPREFIX "no location found after parse"); ++ goto done; ++ } ++ ++ cur_defaults = dup_defaults_entry(defaults_entry); ++ if (!cur_defaults) { ++ error(ap->logopt, MODPREFIX ++ "failed to duplicate defaults entry"); ++ goto done; ++ } ++ ++ head = &entries; ++ p = head->next; ++ while (p != head) { ++ struct amd_entry *this = list_entry(p, struct amd_entry, list); ++ p = p->next; ++ ++ if (this->flags & AMD_DEFAULTS_MERGE) { ++ free_amd_entry(cur_defaults); ++ list_del_init(&this->list); ++ cur_defaults = this; ++ continue; ++ } else if (this->flags & AMD_DEFAULTS_RESET) { ++ struct amd_entry *new; ++ new = dup_defaults_entry(defaults_entry); ++ if (new) { ++ free_amd_entry(cur_defaults); ++ cur_defaults = new; ++ } ++ list_del_init(&this->list); ++ free_amd_entry(this); ++ continue; ++ } ++ ++ update_with_defaults(cur_defaults, this, sv); ++ sv = expand_entry(ap, this, flags, sv); ++ sv = merge_entry_options(ap, this, sv); ++ normalize_sublink(ap->logopt, this, sv); ++ ++ dequote_entry(ap, this); ++ ++ rv = amd_mount(ap, name, this, source, sv, flags, ctxt); ++ if (!rv) ++ break; ++ } ++ free_amd_entry(cur_defaults); ++ ++ if (rv) ++ debug(ap->logopt, "no more locations to try, returning fail"); ++done: ++ free_amd_entry_list(&entries); ++ free_amd_entry(defaults_entry); ++ macro_free_table(sv); ++ ++ return rv; ++} ++ ++int parse_done(void *context) ++{ ++ int rv = 0; ++ struct parse_context *ctxt = (struct parse_context *) context; ++ ++ instance_mutex_lock(); ++ if (--init_ctr == 0) { ++ rv = close_mount(mount_nfs); ++ mount_nfs = NULL; ++ } ++ instance_mutex_unlock(); ++ if (ctxt) ++ kill_context(ctxt); ++ ++ return rv; ++} diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-remopts-handling.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-remopts-handling.patch new file mode 100644 index 0000000..9f2ecd5 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-remopts-handling.patch @@ -0,0 +1,42 @@ +autofs-5.0.9 - amd lookup add remopts handling + +From: Ian Kent + + +--- + modules/parse_amd.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index bf673b3..4cebce8 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -988,20 +988,26 @@ static int do_nfs_mount(struct autofs_point *ap, const char *name, + struct amd_entry *entry, unsigned int flags) + { + char target[PATH_MAX + 1]; ++ unsigned int proximity; ++ char *opts = entry->opts; + int ret = 0; + + strcpy(target, entry->rhost); + strcat(target, ":"); + strcat(target, entry->rfs); + ++ proximity = get_network_proximity(entry->rhost); ++ if (proximity == PROXIMITY_OTHER && entry->remopts) ++ opts = entry->remopts; ++ + if (!entry->sublink) { + ret = mount_nfs->mount_mount(ap, ap->path, name, strlen(name), +- target, entry->type, entry->opts, ++ target, entry->type, opts, + mount_nfs->context); + } else { + if (!is_mounted(_PATH_MOUNTED, entry->fs, MNTS_REAL)) { + ret = mount_nfs->mount_mount(ap, entry->fs, "/", 1, +- target, entry->type, entry->opts, ++ target, entry->type, opts, + mount_nfs->context); + if (ret) + goto out; diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-search_path-handling.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-search_path-handling.patch new file mode 100644 index 0000000..7c4ecd2 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-search_path-handling.patch @@ -0,0 +1,263 @@ +autofs-5.0.9 - amd lookup add search_path handling + +From: Ian Kent + + +--- + daemon/lookup.c | 75 +++++++++++++++++++++++++++++++---------- + include/master.h | 1 + lib/master.c | 6 +++ + man/autofs.conf.5.in | 5 ++ + modules/parse_amd.c | 4 +- + redhat/autofs.conf.default.in | 9 +--- + samples/autofs.conf.default.in | 9 +--- + 7 files changed, 79 insertions(+), 30 deletions(-) + +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -100,25 +100,64 @@ static int do_read_master(struct master + return status; + } + +-static char *find_map_path(struct map_source *map) ++static char *find_map_path(struct autofs_point *ap, struct map_source *map) + { ++ const char *mname = map->argv[0]; ++ unsigned int mlen = strlen(mname); ++ char *tok, *ptr = NULL; ++ char *path = NULL; ++ char *search_path; + struct stat st; +- char *path; + +- path = malloc(strlen(AUTOFS_MAP_DIR) + strlen(map->argv[0]) + 2); +- if (!path) ++ /* ++ * This is different to the way it is in amd. ++ * autofs will always try to locate maps in AUTOFS_MAP_DIR ++ * but amd has no default and will not find a file map that ++ * isn't a full path when no search_path is configured, either ++ * in the mount point or global configuration. ++ */ ++ search_path = strdup(AUTOFS_MAP_DIR); ++ if (map->flags & MAP_FLAG_FORMAT_AMD) { ++ struct autofs_point *pap = ap; ++ char *tmp; ++ /* ++ * Make sure we get search_path from the root of the ++ * mount tree, if one is present in the configuration. ++ * Again different from amd, which ignores the submount ++ * case. ++ */ ++ while (pap->parent) ++ pap = pap->parent; ++ tmp = conf_amd_get_search_path(pap->path); ++ if (tmp) { ++ if (search_path) ++ free(search_path); ++ search_path = tmp; ++ } ++ } ++ if (!search_path) + return NULL; + +- strcpy(path, AUTOFS_MAP_DIR); +- strcat(path, "/"); +- strcat(path, map->argv[0]); +- +- if (!stat(path, &st)) +- return path; +- +- free(path); ++ tok = strtok_r(search_path, ":", &ptr); ++ while (tok) { ++ char *this = malloc(strlen(tok) + mlen + 2); ++ if (!this) { ++ free(search_path); ++ return NULL; ++ } ++ strcpy(this, tok); ++ strcat(this, "/"); ++ strcat(this, mname); ++ if (!stat(this, &st)) { ++ path = this; ++ break; ++ } ++ free(this); ++ tok = strtok_r(NULL, ":", &ptr); ++ } + +- return NULL; ++ free(search_path); ++ return path; + } + + static int read_master_map(struct master *master, char *type, time_t age) +@@ -435,7 +474,7 @@ static int lookup_map_read_map(struct au + if (map->argv[0][0] == '/') + return do_read_map(ap, map, age); + +- path = find_map_path(map); ++ path = find_map_path(ap, map); + if (!path) + return NSS_STATUS_UNKNOWN; + +@@ -479,6 +518,7 @@ static enum nsswitch_status read_map_sou + tmap.flags = map->flags; + tmap.type = this->source; + tmap.format = map->format; ++ tmap.name = map->name; + tmap.lookup = map->lookup; + tmap.mc = map->mc; + tmap.instance = map->instance; +@@ -489,7 +529,7 @@ static enum nsswitch_status read_map_sou + tmap.argc = 0; + tmap.argv = NULL; + +- path = find_map_path(map); ++ path = find_map_path(ap, map); + if (!path) + return NSS_STATUS_UNKNOWN; + +@@ -838,7 +878,7 @@ static int do_name_lookup_mount(struct a + if (map->argv[0][0] == '/') + return do_lookup_mount(ap, map, name, name_len); + +- path = find_map_path(map); ++ path = find_map_path(ap, map); + if (!path) + return NSS_STATUS_UNKNOWN; + +@@ -883,6 +923,7 @@ static enum nsswitch_status lookup_map_n + tmap.flags = map->flags; + tmap.type = this->source; + tmap.format = map->format; ++ tmap.name = map->name; + tmap.mc = map->mc; + tmap.instance = map->instance; + tmap.exp_timeout = map->exp_timeout; +@@ -891,7 +932,7 @@ static enum nsswitch_status lookup_map_n + tmap.argc = 0; + tmap.argv = NULL; + +- path = find_map_path(map); ++ path = find_map_path(ap, map); + if (!path) + return NSS_STATUS_UNKNOWN; + +--- autofs-5.0.7.orig/include/master.h ++++ autofs-5.0.7/include/master.h +@@ -26,6 +26,7 @@ struct map_source { + unsigned int flags; + char *type; + char *format; ++ char *name; + time_t exp_timeout; /* Timeout for expiring mounts */ + time_t age; + unsigned int master_line; +--- autofs-5.0.7.orig/lib/master.c ++++ autofs-5.0.7/lib/master.c +@@ -211,6 +211,8 @@ master_add_map_source(struct master_mape + } + source->argc = argc; + source->argv = tmpargv; ++ if (source->argv[0]) ++ source->name = strdup(source->argv[0]); + + master_source_writelock(entry); + +@@ -333,6 +335,8 @@ static void __master_free_map_source(str + free(source->type); + if (source->format) + free(source->format); ++ if (source->name) ++ free(source->name); + if (free_cache && source->mc) + cache_release(source); + if (source->lookup) { +@@ -468,6 +472,8 @@ master_add_source_instance(struct map_so + } + new->argc = argc; + new->argv = tmpargv; ++ if (source->name) ++ new->name = strdup(source->name); + + status = pthread_mutex_lock(&instance_mutex); + if (status) +--- autofs-5.0.7.orig/man/autofs.conf.5.in ++++ autofs-5.0.7/man/autofs.conf.5.in +@@ -327,6 +327,11 @@ and can be used to provide different def + without having to modify centrally managed maps. It is empty by + default. + .TP ++.B search_path ++.br ++Colon seperated paths to search for maps that are not specified ++as a full path. ++.TP + .B dismount_interval + .br + Is equivalent to the autofs timeout option. It is only possible +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -198,7 +198,9 @@ static struct substvar *add_lookup_vars( + break; + } + +- if (source->argv[0][0]) ++ if (source->name) ++ list = macro_addvar(list, "map", 3, source->name); ++ else if (source->argv[0][0]) + list = macro_addvar(list, "map", 3, source->argv[0]); + + tsv = pthread_getspecific(key_thread_stdenv_vars); +--- autofs-5.0.7.orig/redhat/autofs.conf.default.in ++++ autofs-5.0.7/redhat/autofs.conf.default.in +@@ -221,12 +221,6 @@ mount_nfs_default_protocol = 4 + # + # A number of configuration options are not yet implemented: + # +-# search_path - always a little frustrating, the compiled in +-# map location should be used to locate maps but isn't +-# in some cases. This requires work within autofs itself +-# and that will (obviously) include implementing this +-# configuration option for the amd map parser as well. +-# + # fully_qualified_hosts - not yet implemented. + # + # unmount_on_exit - since autofs always tries to re-connect +@@ -269,6 +263,9 @@ mount_nfs_default_protocol = 4 + # machines without having to modify centrally managed maps. + # It is empty by default. + # ++# search_path - colon seperated paths to search for maps that ++# are not specified as a full path. ++# + # dismount_interval - is equivalent to the autofs timeout option. It + # is only possible to use this with type "auto" mounts due + # to the way the autofs kernel module performs expiry. It +--- autofs-5.0.7.orig/samples/autofs.conf.default.in ++++ autofs-5.0.7/samples/autofs.conf.default.in +@@ -220,12 +220,6 @@ browse_mode = no + # + # A number of configuration options are not yet implemented: + # +-# search_path - always a little frustrating, the compiled in +-# map location should be used to locate maps but isn't +-# in some cases. This requires work within autofs itself +-# and that will (obviously) include implementing this +-# configuration option for the amd map parser as well. +-# + # fully_qualified_hosts - not yet implemented. + # + # unmount_on_exit - since autofs always tries to re-connect +@@ -268,6 +262,9 @@ browse_mode = no + # machines without having to modify centrally managed maps. + # It is empty by default. + # ++# search_path - colon seperated paths to search for maps that ++# are not specified as a full path. ++# + # dismount_interval - is equivalent to the autofs timeout option. It + # is only possible to use this with type "auto" mounts due + # to the way the autofs kernel module performs expiry. It diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-selector-handling-functions.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-selector-handling-functions.patch new file mode 100644 index 0000000..62cd55e --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-selector-handling-functions.patch @@ -0,0 +1,233 @@ +autofs-5.0.999999999 - amd lookup add selector handling functions + +From: Ian Kent + + +--- + include/parse_subs.h | 77 +++++++++++++++++++++++++++++++++ + lib/parse_subs.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 194 insertions(+) + +diff --git a/include/parse_subs.h b/include/parse_subs.h +index 675411d..a416c59 100644 +--- a/include/parse_subs.h ++++ b/include/parse_subs.h +@@ -25,6 +25,83 @@ + #define PROXIMITY_OTHER 0x0008 + #define PROXIMITY_UNSUPPORTED 0x0010 + ++#define SEL_ARCH 0x00000001 ++#define SEL_KARCH 0x00000002 ++#define SEL_OS 0x00000004 ++#define SEL_OSVER 0x00000008 ++#define SEL_FULL_OS 0x00000010 ++#define SEL_VENDOR 0x00000020 ++#define SEL_HOST 0x00000040 ++#define SEL_HOSTD 0x00000080 ++#define SEL_XHOST 0x00000100 ++#define SEL_DOMAIN 0x00000200 ++#define SEL_BYTE 0x00000400 ++#define SEL_CLUSTER 0x00000800 ++#define SEL_NETGRP 0x00001000 ++#define SEL_NETGRPD 0x00002000 ++#define SEL_IN_NETWORK 0x00004000 ++#define SEL_UID 0x00008000 ++#define SEL_GID 0x00010000 ++#define SEL_KEY 0x00020000 ++#define SEL_MAP 0x00040000 ++#define SEL_PATH 0x00080000 ++#define SEL_EXISTS 0x00100000 ++#define SEL_AUTODIR 0x00200000 ++#define SEL_DOLLAR 0x00400000 ++#define SEL_TRUE 0x00800000 ++#define SEL_FALSE 0x01000000 ++ ++#define SEL_COMP_NONE 0x0000 ++#define SEL_COMP_EQUAL 0x0001 ++#define SEL_COMP_NOTEQUAL 0x0002 ++#define SEL_COMP_NOT 0x0004 ++ ++#define SEL_FLAG_MACRO 0x0001 ++#define SEL_FLAG_FUNC1 0x0002 ++#define SEL_FLAG_FUNC2 0x0004 ++#define SEL_FLAG_STR 0x0100 ++#define SEL_FLAG_NUM 0x0200 ++#define SEL_FLAG_BOOL 0x0400 ++ ++#define SEL_FLAGS_TYPE_MASK 0x00FF ++#define SEL_FLAGS_VALUE_MASK 0xFF00 ++#define SEL_FREE_VALUE_MASK (SEL_FLAG_MACRO|SEL_FLAG_STR|SEL_FLAG_NUM) ++#define SEL_FREE_ARG1_MASK (SEL_FLAG_FUNC1) ++#define SEL_FREE_ARG2_MASK (SEL_FLAG_FUNC2) ++ ++struct type_compare { ++ char *value; ++}; ++ ++struct type_function { ++ char *arg1; ++ char *arg2; ++}; ++ ++struct sel { ++ unsigned long selector; ++ const char *name; ++ unsigned int flags; ++ struct sel *next; ++}; ++ ++struct selector { ++ struct sel *sel; ++ unsigned int compare; ++ ++ union { ++ struct type_compare comp; ++ struct type_function func; ++ }; ++ ++ struct selector *next; ++}; ++ ++void sel_hash_init(void); ++struct sel *sel_lookup(const char *); ++struct selector *get_selector(char *); ++void free_selector(struct selector *); ++ + struct mapent; + + struct map_type_info { +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index 279f40e..f485a4c 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -45,6 +45,44 @@ static int volatile ifc_last_len = 0; + #define EXPAND_LEADING_DOT 0x0004 + #define EXPAND_TRAILING_DOT 0x0008 + ++#define SELECTOR_HASH_SIZE 20 ++ ++static struct sel sel_table[] = { ++ { SEL_ARCH, "arch", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_KARCH, "karch", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_OS, "os", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_OSVER, "osver", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_FULL_OS, "full_os", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_VENDOR, "vendor", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_HOST, "host", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_HOSTD, "hostd", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_XHOST, "xhost", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL }, ++ { SEL_DOMAIN, "domain", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_BYTE, "byte", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_CLUSTER, "cluster", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_NETGRP, "netgrp", SEL_FLAG_FUNC2|SEL_FLAG_BOOL, NULL }, ++ { SEL_NETGRPD, "netgrpd", SEL_FLAG_FUNC2|SEL_FLAG_BOOL, NULL }, ++ { SEL_IN_NETWORK, "in_network", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL }, ++ { SEL_IN_NETWORK, "netnumber", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL }, ++ { SEL_IN_NETWORK, "network", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL }, ++ { SEL_IN_NETWORK, "wire", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL }, ++ { SEL_UID, "uid", SEL_FLAG_MACRO|SEL_FLAG_NUM, NULL }, ++ { SEL_GID, "gid", SEL_FLAG_MACRO|SEL_FLAG_NUM, NULL }, ++ { SEL_KEY, "key", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_MAP, "map", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_PATH, "path", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_EXISTS, "exists", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL }, ++ { SEL_AUTODIR, "autodir", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_DOLLAR, "dollar", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL }, ++ { SEL_TRUE, "true", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL }, ++ { SEL_FALSE, "false", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL }, ++}; ++static unsigned int sel_count = sizeof(sel_table)/sizeof(struct sel); ++ ++static struct sel *sel_hash[SELECTOR_HASH_SIZE]; ++static unsigned int sel_hash_init_done = 0; ++static pthread_mutex_t sel_hash_mutex = PTHREAD_MUTEX_INITIALIZER; ++ + struct types { + char *type; + unsigned int len; +@@ -70,6 +108,85 @@ static struct types format_type[] = { + }; + static unsigned int format_type_count = sizeof(format_type)/sizeof(struct types); + ++static void sel_add(struct sel *sel) ++{ ++ u_int32_t hval = hash(sel->name, SELECTOR_HASH_SIZE); ++ struct sel *old; ++ ++ old = sel_hash[hval]; ++ sel_hash[hval] = sel; ++ sel_hash[hval]->next = old; ++} ++ ++void sel_hash_init(void) ++{ ++ int i; ++ ++ pthread_mutex_lock(&sel_hash_mutex); ++ if (sel_hash_init_done) { ++ pthread_mutex_unlock(&sel_hash_mutex); ++ return; ++ } ++ for (i = 0; i < SELECTOR_HASH_SIZE; i++) ++ sel_hash[i] = NULL; ++ ++ for (i = 0; i < sel_count; i++) ++ sel_add(&sel_table[i]); ++ ++ sel_hash_init_done = 1; ++ pthread_mutex_unlock(&sel_hash_mutex); ++} ++ ++struct sel *sel_lookup(const char *name) ++{ ++ u_int32_t hval = hash(name, SELECTOR_HASH_SIZE); ++ struct sel *sel; ++ ++ pthread_mutex_lock(&sel_hash_mutex); ++ for (sel = sel_hash[hval]; sel != NULL; sel = sel->next) { ++ if (strcmp(name, sel->name) == 0) { ++ pthread_mutex_unlock(&sel_hash_mutex); ++ return sel; ++ } ++ } ++ pthread_mutex_unlock(&sel_hash_mutex); ++ return NULL; ++} ++ ++struct selector *get_selector(char *name) ++{ ++ struct sel *sel; ++ ++ sel = sel_lookup(name); ++ if (sel) { ++ struct selector *new = malloc(sizeof(struct selector)); ++ if (!new) ++ return NULL; ++ memset(new, 0, sizeof(*new)); ++ new->sel = sel; ++ return new; ++ } ++ return NULL; ++} ++ ++void free_selector(struct selector *selector) ++{ ++ struct selector *s = selector; ++ struct selector *next = s; ++ ++ while (s) { ++ next = s->next; ++ if (s->sel->flags & SEL_FREE_VALUE_MASK) ++ free(s->comp.value); ++ if (s->sel->flags & SEL_FREE_ARG1_MASK) ++ free(s->func.arg1); ++ if (s->sel->flags & SEL_FREE_ARG2_MASK) ++ free(s->func.arg2); ++ s = next; ++ } ++ return; ++} ++ + static unsigned int ipv6_mask_cmp(uint32_t *host, uint32_t *iface, uint32_t *mask) + { + unsigned int ret = 1; diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-selector-handling.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-selector-handling.patch new file mode 100644 index 0000000..c77ca64 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-selector-handling.patch @@ -0,0 +1,775 @@ +autofs-5.0.9 - amd lookup add selector handling + +From: Ian Kent + + +--- + include/parse_subs.h | 2 + lib/parse_subs.c | 127 ++++++++++++++++++ + modules/amd_parse.y | 49 ++++++- + modules/amd_tok.l | 73 ++++++++++ + modules/parse_amd.c | 348 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 586 insertions(+), 13 deletions(-) + +diff --git a/include/parse_subs.h b/include/parse_subs.h +index a416c59..43da182 100644 +--- a/include/parse_subs.h ++++ b/include/parse_subs.h +@@ -111,6 +111,8 @@ struct map_type_info { + }; + + unsigned int get_proximity(struct sockaddr *); ++unsigned int get_network_proximity(const char *); ++unsigned int in_network(char *); + const char *skipspace(const char *); + int check_colon(const char *); + int chunklen(const char *, int); +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index f485a4c..de5319f 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -19,9 +19,13 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include ++#include ++ + #include "automount.h" + + #define MAX_OPTIONS_LEN 256 +@@ -370,6 +374,129 @@ unsigned int get_proximity(struct sockaddr *host_addr) + return PROXIMITY_OTHER; + } + ++static char *inet_fill_net(const char *net_num, char *net) ++{ ++ char *np; ++ unsigned int dots = 3; ++ ++ if (strlen(net_num) > INET_ADDRSTRLEN) ++ return NULL; ++ ++ if (!isdigit(*net_num)) ++ return NULL; ++ ++ *net = '\0'; ++ strcpy(net, net_num); ++ ++ np = net; ++ while (*np++) { ++ if (*np == '.') { ++ np++; ++ dots--; ++ if (!*np && dots) ++ strcat(net, "0"); ++ continue; ++ } ++ ++ if ((*np && !isdigit(*np)) || dots < 0) { ++ *net = '\0'; ++ return NULL; ++ } ++ } ++ ++ while (dots--) ++ strcat(net, ".0"); ++ ++ return net; ++} ++ ++static char *get_network_number(const char *network) ++{ ++ struct netent *netent; ++ char cnet[MAX_NETWORK_LEN]; ++ uint32_t h_net; ++ size_t len; ++ ++ len = strlen(network) + 1; ++ if (len > MAX_NETWORK_LEN) ++ return NULL; ++ ++ netent = getnetbyname(network); ++ if (!netent) ++ return NULL; ++ h_net = ntohl(netent->n_net); ++ ++ if (!inet_ntop(AF_INET, &h_net, cnet, INET_ADDRSTRLEN)) ++ return NULL; ++ ++ return strdup(cnet); ++} ++ ++unsigned int get_network_proximity(const char *name) ++{ ++ struct addrinfo hints; ++ struct addrinfo *ni, *this; ++ char name_or_num[NI_MAXHOST]; ++ unsigned int proximity; ++ char *net; ++ int ret; ++ ++ if (!name) ++ return PROXIMITY_ERROR; ++ ++ net = get_network_number(name); ++ if (net) ++ strcpy(name_or_num, net); ++ else { ++ char this[NI_MAXHOST]; ++ char *mask; ++ ++ strcpy(this, name); ++ if ((mask = strchr(this, '/'))) ++ *mask++ = '\0'; ++ if (!strchr(this, '.')) ++ strcpy(name_or_num, this); ++ else { ++ char buf[NI_MAXHOST], *new; ++ new = inet_fill_net(this, buf); ++ if (!new) ++ return PROXIMITY_ERROR; ++ strcpy(name_or_num, new); ++ } ++ } ++ ++ memset(&hints, 0, sizeof(struct addrinfo)); ++ hints.ai_family = AF_UNSPEC; ++ hints.ai_socktype = SOCK_DGRAM; ++ ++ ret = getaddrinfo(name_or_num, NULL, &hints, &ni); ++ if (ret) { ++ logerr("getaddrinfo: %s", gai_strerror(ret)); ++ return PROXIMITY_ERROR; ++ } ++ ++ proximity = PROXIMITY_OTHER; ++ ++ this = ni; ++ while (this) { ++ unsigned int prx = get_proximity(this->ai_addr); ++ if (prx < proximity) ++ proximity = prx; ++ this = this->ai_next; ++ } ++ ++ return proximity; ++} ++ ++unsigned int in_network(char *network) ++{ ++ unsigned int proximity = get_network_proximity(network); ++ if (proximity == PROXIMITY_ERROR || ++ proximity > PROXIMITY_SUBNET) ++ return 0; ++ return 1; ++} ++ + /* + * Skip whitespace in a string; if we hit a #, consider the rest of the + * entry a comment. +diff --git a/modules/amd_parse.y b/modules/amd_parse.y +index 33106a1..71fd569 100644 +--- a/modules/amd_parse.y ++++ b/modules/amd_parse.y +@@ -92,6 +92,9 @@ static int amd_fprintf(FILE *, char *, ...); + %token NOT_EQUAL + %token COMMA + %token OPTION_ASSIGN ++%token LBRACKET ++%token RBRACKET ++%token NOT + %token NILL + + %token MAP_OPTION +@@ -102,6 +105,7 @@ static int amd_fprintf(FILE *, char *, ...); + %token MNT_OPTION + %token SELECTOR + %token SELECTOR_VALUE ++%token SEL_ARG_VALUE + %token OPTION + %token MACRO + %token OTHER +@@ -187,18 +191,46 @@ selector_or_option: selection + + selection: SELECTOR IS_EQUAL SELECTOR_VALUE + { +- if (!make_selector($1, $3, NULL, SEL_TYPE_EQUAL)) { ++ if (!make_selector($1, $3, NULL, SEL_COMP_EQUAL)) { + amd_notify($1); + YYABORT; + } + } + | SELECTOR NOT_EQUAL SELECTOR_VALUE + { +- if (!make_selector($1, $3, NULL, SEL_TYPE_NOTEQUAL)) { ++ if (!make_selector($1, $3, NULL, SEL_COMP_NOTEQUAL)) { + amd_notify($1); + YYABORT; + } + } ++ | SELECTOR LBRACKET SEL_ARG_VALUE RBRACKET ++ { ++ if (!make_selector($1, $3, NULL, SEL_COMP_NONE)) { ++ amd_notify($1); ++ YYABORT; ++ } ++ } ++ | SELECTOR LBRACKET SEL_ARG_VALUE COMMA SEL_ARG_VALUE RBRACKET ++ { ++ if (!make_selector($1, $3, $5, SEL_COMP_NONE)) { ++ amd_notify($1); ++ YYABORT; ++ } ++ } ++ | NOT SELECTOR LBRACKET SEL_ARG_VALUE RBRACKET ++ { ++ if (!make_selector($2, $4, NULL, SEL_COMP_NOT)) { ++ amd_notify($2); ++ YYABORT; ++ } ++ } ++ | NOT SELECTOR LBRACKET SEL_ARG_VALUE COMMA SEL_ARG_VALUE RBRACKET ++ { ++ if (!make_selector($2, $4, $6, SEL_COMP_NOT)) { ++ amd_notify($2); ++ YYABORT; ++ } ++ } + ; + + option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE +@@ -388,9 +420,6 @@ static int make_selector(char *name, + if (!sel_lookup(name)) + return 0; + +- if (!value1) +- return 0; +- + s = get_selector(name); + if (!s) + return 0; +@@ -401,9 +430,13 @@ static int make_selector(char *name, + goto error; + s->comp.value = tmp; + } else if (s->sel->flags & SEL_FLAG_FUNC1) { +- char *tmp = amd_strdup(value1); +- if (!tmp) +- goto error; ++ if (!value1) ++ tmp = NULL; ++ else { ++ char *tmp = amd_strdup(value1); ++ if (!tmp) ++ goto error; ++ } + s->func.arg1 = tmp; + } else if (s->sel->flags & SEL_FLAG_FUNC2) { + char *tmp = amd_strdup(value1); +diff --git a/modules/amd_tok.l b/modules/amd_tok.l +index afa3a87..cea9ea5 100644 +--- a/modules/amd_tok.l ++++ b/modules/amd_tok.l +@@ -70,22 +70,29 @@ int amd_yyinput(char *, int); + + %option nounput + +-%x MAPOPTVAL FSOPTVAL MNTOPTVAL SELOPTVAL ++%x MAPOPTVAL FSOPTVAL MNTOPTVAL SELOPTVAL SELARGVAL + + NL \r?\n + OPTWS [[:blank:]]* + OTHR [^!;:=/|\- \t\r\n#]* + ++V4NUM ([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5]) ++ + MACRO (\$\{([[:alpha:]_/]([[:alnum:]_\-])([[:alnum:]_\-/])*)\}) + QSTR (\"([^"\\]|\\.)*\") + OSTR ([[:alpha:]]([[:alnum:]_\-])+) + FSTR ([[:alnum:]_/\.]([[:alnum:]_\-/\.]|(\\.))*) + VSTR (([[:alnum:]_\-\:/\.])+) + SSTR ([[:alpha:]]([[:alnum:]\-\.])+) ++IP4ADDR ({V4NUM}\.((({V4NUM}\.){0,2}){V4NUM}?)) ++V4MASK ({IP4ADDR}|([1-2][0-9]|3[0-2]|[1-9])) ++IP6ADDR ((([A-Fa-f0-9]{1,4}\:\:?){1,7}[A-Fa-f0-9]{1,4})|(\:\:1)) ++V6MASK (12[0-8]|1[0-1][0-9]|[1-9][0-9]|[1-9]) + + FOPT (({QSTR}|{FSTR}|{MACRO})+) + OPTS ({OSTR}(=({VSTR}|{QSTR}|{MACRO})+)?) + SOPT (({SSTR}|{QSTR}|{MACRO})+) ++NOPT ({SSTR}|(({IP4ADDR}(\/{V4MASK})?)|({IP6ADDR}(\/{V6MASK})?))) + + MAPOPT (fs|type|maptype|pref|sublink|delay) + MNTOPT (opts|addopts|remopts) +@@ -94,13 +101,16 @@ MAPTYPE (file|nis|nisplus|ldap|hesiod|exec|ndbm|passwd|union) + FSTYPE (auto|nfs|link|host|nfsx|ufs|xfs|efs) + + OSSEL (arch|karch|os|osver|full_os|vendor) +-HSTSEL (host|hostd|xhost|domain|byte|cluster) +-NETSEL (netnumber|network|wire|netgrp|netgrpd|in_network) ++HSTSEL (host|hostd|domain|byte|cluster) ++NETSEL (netnumber|network|wire|in_network) + USRSEL (uid|gid) + MAPSEL (key|map|path) +-OTRSEL (exists|autodir|dollar) ++OTRSEL (autodir|dollar) + BOLSEL (true|false) +-SELOPT ({OSSEL}|{HSTSEL}|{NETSEL}|{BOLSEL}|{USRSEL}|{MAPSEL}|{OTRSEL}) ++ ++SELOPT ({OSSEL}|{HSTSEL}|{USRSEL}|{MAPSEL}|{OTRSEL}) ++SEL1ARG (xhost|exists|{NETSEL}|{BOLSEL}) ++SEL2ARG (netgrp|netgrpd) + + CUTSEP (\|\||\/) + +@@ -135,6 +145,20 @@ CUTSEP (\|\||\/) + return SELECTOR; + } + ++ "!"/({SEL1ARG}|{SEL2ARG}) { return NOT; } ++ ++ {SEL1ARG} { ++ BEGIN(SELARGVAL); ++ strcpy(amd_lval.strtype, amd_text); ++ return SELECTOR; ++ } ++ ++ {SEL2ARG} { ++ BEGIN(SELARGVAL); ++ strcpy(amd_lval.strtype, amd_text); ++ return SELECTOR; ++ } ++ + {CUTSEP} { return CUT; } + + "-" { return HYPHEN; } +@@ -263,6 +287,45 @@ CUTSEP (\|\||\/) + } + } + ++{ ++ {NL} | ++ \x00 { ++ BEGIN(INITIAL); ++ yyless(1); ++ } ++ ++ ";" { ++ BEGIN(INITIAL); ++ return SEPERATOR; ++ } ++ ++ "(" { return LBRACKET; } ++ ++ {NOPT} { ++ strcpy(amd_lval.strtype, amd_text); ++ return SEL_ARG_VALUE; ++ } ++ ++ {SOPT}/"," { ++ strcpy(amd_lval.strtype, amd_text); ++ return SEL_ARG_VALUE; ++ } ++ ++ "," { return COMMA; } ++ ++ {SOPT} { ++ strcpy(amd_lval.strtype, amd_text); ++ return SEL_ARG_VALUE; ++ } ++ ++ {FOPT} { ++ strcpy(amd_lval.strtype, amd_text); ++ return SEL_ARG_VALUE; ++ } ++ ++ ")" { return RBRACKET; } ++} ++ + %% + + #include "automount.h" +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 35cc5dc..d9c7d9b 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -223,6 +223,307 @@ static struct substvar *add_lookup_vars(struct autofs_point *ap, + return list; + } + ++static int match_my_name(unsigned int logopt, const char *name, struct substvar *sv) ++{ ++ struct addrinfo hints, *cni, *ni, *haddr; ++ char host[NI_MAXHOST + 1], numeric[NI_MAXHOST + 1]; ++ const struct substvar *v; ++ int rv = 0, ret; ++ ++ v = macro_findvar(sv, "host", 4); ++ if (v) { ++ if (!strcmp(v->val, name)) ++ return 1; ++ } ++ ++ /* Check if comparison value is an alias */ ++ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_flags = AI_CANONNAME; ++ hints.ai_family = AF_UNSPEC; ++ hints.ai_socktype = SOCK_DGRAM; ++ ++ /* Get host canonical name */ ++ ret = getaddrinfo(v->val, NULL, &hints, &cni); ++ if (ret) { ++ error(logopt, ++ "hostname lookup failed: %s\n", gai_strerror(ret)); ++ goto out; ++ } ++ ++ hints.ai_flags = 0; ++ ++ /* Resolve comparison name to its names and compare */ ++ ret = getaddrinfo(name, NULL, &hints, &ni); ++ if (ret) { ++ error(logopt, ++ "hostname lookup failed: %s\n", gai_strerror(ret)); ++ freeaddrinfo(cni); ++ goto out; ++ } ++ ++ haddr = ni; ++ while (haddr) { ++ /* Translate the host address into a numeric string form */ ++ ret = getnameinfo(haddr->ai_addr, haddr->ai_addrlen, ++ numeric, sizeof(numeric), NULL, 0, ++ NI_NUMERICHOST); ++ if (ret) { ++ error(logopt, ++ "host address info lookup failed: %s\n", ++ gai_strerror(ret)); ++ freeaddrinfo(cni); ++ goto next; ++ } ++ ++ /* Try to resolve back again to get the canonical name */ ++ ret = getnameinfo(haddr->ai_addr, haddr->ai_addrlen, ++ host, NI_MAXHOST, NULL, 0, 0); ++ if (ret) { ++ error(logopt, ++ "host address info lookup failed: %s\n", ++ gai_strerror(ret)); ++ freeaddrinfo(cni); ++ goto next; ++ } ++ ++ if (!strcmp(host, cni->ai_canonname)) { ++ rv = 1; ++ break; ++ } ++next: ++ haddr = haddr->ai_next; ++ } ++ freeaddrinfo(ni); ++ freeaddrinfo(cni); ++out: ++ return rv; ++} ++ ++static int eval_selector(unsigned int logopt, ++ struct amd_entry *this, struct substvar *sv) ++{ ++ struct selector *s = this->selector; ++ const struct substvar *v; ++ unsigned int s_type; ++ unsigned int v_type; ++ struct stat st; ++ char *host; ++ int res, val, ret = 0; ++ ++ s_type = s->sel->flags & SEL_FLAGS_TYPE_MASK; ++ ++ switch (s_type) { ++ case SEL_FLAG_MACRO: ++ v = macro_findvar(sv, s->sel->name, strlen(s->sel->name)); ++ if (!v) { ++ error(logopt, "failed to get selector %s", s->sel->name); ++ return 0; ++ } ++ ++ v_type = s->sel->flags & SEL_FLAGS_VALUE_MASK; ++ ++ switch (v_type) { ++ case SEL_FLAG_STR: ++ res = strcmp(v->val, s->comp.value); ++ if (s->compare & SEL_COMP_EQUAL && !res) { ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s) == %s", ++ v->def, v->val, s->comp.value); ++ ret = 1; ++ break; ++ } else if (s->compare & SEL_COMP_NOTEQUAL && res) { ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s) != %s", ++ v->def, v->val, s->comp.value); ++ ret = 1; ++ break; ++ } ++ ++ debug(logopt, MODPREFIX ++ "did not match selector %s(%s) %s %s", ++ v->def, v->val, ++ (s->compare & SEL_COMP_EQUAL ? "==" : "!="), ++ s->comp.value); ++ break; ++ ++ case SEL_FLAG_NUM: ++ res = atoi(v->val); ++ val = atoi(s->comp.value); ++ if (s->compare & SEL_COMP_EQUAL && res == val) { ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s) equal to %s", ++ v->def, v->val, s->comp.value); ++ ret = 1; ++ break; ++ } else if (s->compare & SEL_COMP_NOTEQUAL && res != val) { ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s) not equal to %s", ++ v->def, v->val, s->comp.value); ++ ret = 1; ++ break; ++ } ++ ++ debug(logopt, MODPREFIX ++ "did not match selector %s(%s) %s %s", ++ v->def, v->val, ++ (s->compare & SEL_COMP_EQUAL ? "==" : "!="), ++ s->comp.value); ++ break; ++ ++ default: ++ break; ++ } ++ break; ++ ++ case SEL_FLAG_FUNC1: ++ if (s->sel->selector != SEL_TRUE && ++ s->sel->selector != SEL_FALSE && ++ !s->func.arg1) { ++ error(logopt, MODPREFIX ++ "expected argument missing for selector %s", ++ s->sel->name); ++ break; ++ } ++ ++ switch (s->sel->selector) { ++ case SEL_TRUE: ++ ret = 1; ++ if (s->compare == SEL_COMP_NOT) ++ ret = !ret; ++ if (ret) ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s)", ++ s->sel->name, s->func.arg1); ++ else ++ debug(logopt, MODPREFIX ++ "did not match selector %s(%s)", ++ s->sel->name, s->func.arg1); ++ break; ++ ++ case SEL_FALSE: ++ if (s->compare == SEL_COMP_NOT) ++ ret = !ret; ++ if (ret) ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s)", ++ s->sel->name, s->func.arg1); ++ else ++ debug(logopt, MODPREFIX ++ "did not match selector %s(%s)", ++ s->sel->name, s->func.arg1); ++ break; ++ ++ case SEL_XHOST: ++ ret = match_my_name(logopt, s->func.arg1, sv); ++ if (s->compare == SEL_COMP_NOT) ++ ret = !ret; ++ if (ret) ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s) to host name", ++ s->sel->name, s->func.arg1); ++ else ++ debug(logopt, MODPREFIX ++ "did not match selector %s(%s) to host name", ++ s->sel->name, s->func.arg1); ++ break; ++ ++ case SEL_EXISTS: ++ /* Sould be OK to fail on any error here */ ++ ret = !lstat(s->func.arg1, &st); ++ if (s->compare == SEL_COMP_NOT) ++ ret = !ret; ++ if (ret) ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s)", ++ s->sel->name, s->func.arg1); ++ else ++ debug(logopt, MODPREFIX ++ "did not match selector %s(%s)", ++ s->sel->name, s->func.arg1); ++ break; ++ ++ case SEL_IN_NETWORK: ++ ret = in_network(s->func.arg1); ++ if (s->compare == SEL_COMP_NOT) ++ ret = !ret; ++ if (ret) ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s)", ++ s->sel->name, s->func.arg1); ++ else ++ debug(logopt, MODPREFIX ++ "did not match selector %s(%s)", ++ s->sel->name, s->func.arg1); ++ break; ++ ++ default: ++ break; ++ } ++ break; ++ ++ case SEL_FLAG_FUNC2: ++ if (!s->func.arg1) { ++ error(logopt, MODPREFIX ++ "expected argument missing for selector %s", ++ s->sel->name); ++ break; ++ } ++ ++ switch (s->sel->selector) { ++ case SEL_NETGRP: ++ case SEL_NETGRPD: ++ if (s->func.arg2) ++ host = s->func.arg2; ++ else { ++ if (s->sel->selector == SEL_NETGRP) ++ v = macro_findvar(sv, "host", 4); ++ else ++ v = macro_findvar(sv, "hostd", 5); ++ if (!v || !*v->val) { ++ error(logopt, ++ "failed to get value of ${host}"); ++ break; ++ } ++ host = v->val; ++ } ++ ret = innetgr(s->func.arg1, host, NULL, NULL); ++ if (s->compare == SEL_COMP_NOT) ++ ret = !ret; ++ if (ret) { ++ if (!s->func.arg2) ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s)", ++ s->sel->name, s->func.arg1); ++ else ++ debug(logopt, MODPREFIX ++ "matched selector %s(%s,%s)", ++ s->sel->name, s->func.arg1, ++ s->func.arg2); ++ } else { ++ if (!s->func.arg2) ++ debug(logopt, MODPREFIX ++ "did not match selector %s(%s)", ++ s->sel->name, s->func.arg1); ++ else ++ debug(logopt, MODPREFIX ++ "did not match selector %s(%s,%s)", ++ s->sel->name, s->func.arg1, s->func.arg2); ++ } ++ break; ++ ++ default: ++ break; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ + static void update_with_defaults(struct amd_entry *defaults, + struct amd_entry *entry, + struct substvar *sv) +@@ -884,6 +1185,33 @@ static void update_prefix(struct autofs_point *ap, + return; + } + ++static int match_selectors(unsigned int logopt, ++ struct amd_entry *entry, struct substvar *sv) ++{ ++ struct selector *s = entry->selector; ++ int ret; ++ ++ /* No selectors, always match */ ++ if (!s) { ++ debug(logopt, "no selectors found in location"); ++ return 1; ++ } ++ ++ ret = 0; ++ ++ /* All selectors must match */ ++ while (s) { ++ ret = eval_selector(logopt, entry, sv); ++ if (!ret) ++ break; ++ s = s->next; ++ } ++ if (!s) ++ ret = 1; ++ ++ return ret; ++} ++ + static struct amd_entry *dup_defaults_entry(struct amd_entry *defaults) + { + struct amd_entry *entry; +@@ -1008,6 +1336,23 @@ static struct amd_entry *select_default_entry(struct autofs_point *ap, + free_amd_entry(this); + continue; + } ++ ++ /* ++ * This probably should be a fail since we expect ++ * selectors to pick the default entry. ++ */ ++ if (!this->selector) ++ continue; ++ ++ if (match_selectors(ap->logopt, this, sv)) { ++ if (entry_default) { ++ /*update_with_defaults(entry_default, this, sv);*/ ++ free_amd_entry(entry_default); ++ } ++ list_del_init(&this->list); ++ defaults_entry = this; ++ break; ++ } + } + + /* Not strickly amd semantics but ... */ +@@ -1195,6 +1540,9 @@ int parse_mount(struct autofs_point *ap, const char *name, + continue; + } + ++ if (!match_selectors(ap->logopt, this, sv)) ++ continue; ++ + update_with_defaults(cur_defaults, this, sv); + sv = expand_entry(ap, this, flags, sv); + sv = merge_entry_options(ap, this, sv); diff --git a/SOURCES/autofs-5.0.9-amd-lookup-add-ufs-fs-type.patch b/SOURCES/autofs-5.0.9-amd-lookup-add-ufs-fs-type.patch new file mode 100644 index 0000000..5475e0f --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-add-ufs-fs-type.patch @@ -0,0 +1,227 @@ +autofs-5.0.9 - amd lookup add ufs fs type + +From: Ian Kent + +Completely overlooked mount type ufs, which should be the +system default filesystem. + +There's no simple way to determine what the system default +filesystem is and am-utils needs to be continually updated +to do this and can easily get it wrong anyway. + +A better approach is to use a configuration entry and set +it to be what it usually is in am-utils, allowing the user +to set it to what they would like it to be. +--- + include/defaults.h | 2 ++ + include/parse_amd.h | 9 +++++---- + lib/defaults.c | 10 ++++++++++ + man/autofs.conf.5.in | 9 +++++++++ + modules/amd_parse.y | 3 +++ + modules/amd_tok.l | 2 +- + modules/parse_amd.c | 21 +++++++++++++++++++++ + redhat/autofs.conf.default.in | 9 +++++++++ + samples/autofs.conf.default.in | 9 +++++++++ + 9 files changed, 69 insertions(+), 5 deletions(-) + +diff --git a/include/defaults.h b/include/defaults.h +index 033acaf..6ca20d0 100644 +--- a/include/defaults.h ++++ b/include/defaults.h +@@ -130,6 +130,7 @@ + #define DEFAULT_AMD_UMOUNT_ON_EXIT "yes" + #define DEFAULT_AMD_USE_TCPWRAPPERS DEFAULT_AMD_NULL_VALUE + #define DEFAULT_AMD_VENDOR "unknown" ++#define DEFAULT_AMD_LINUX_UFS_MOUNT_TYPE "ext3" + + #ifdef WITH_LDAP + struct ldap_schema; +@@ -184,6 +185,7 @@ char *conf_amd_get_map_defaults(const char *); + char *conf_amd_get_map_type(const char *); + char *conf_amd_get_search_path(const char *); + unsigned int conf_amd_get_dismount_interval(const char *); ++char *conf_amd_get_linux_ufs_mount_type(void); + unsigned long conf_amd_get_flags(const char *); + + #endif +diff --git a/include/parse_amd.h b/include/parse_amd.h +index 401aadb..313edd5 100644 +--- a/include/parse_amd.h ++++ b/include/parse_amd.h +@@ -25,10 +25,11 @@ + #define AMD_MOUNT_TYPE_LINKX 0x00000040 + #define AMD_MOUNT_TYPE_LOFS 0x00000080 + #define AMD_MOUNT_TYPE_EXT 0x00000100 +-#define AMD_MOUNT_TYPE_XFS 0x00000200 +-#define AMD_MOUNT_TYPE_JFS 0x00000400 +-#define AMD_MOUNT_TYPE_CACHEFS 0x00000800 +-#define AMD_MOUNT_TYPE_CDFS 0x00001000 ++#define AMD_MOUNT_TYPE_UFS 0x00000200 ++#define AMD_MOUNT_TYPE_XFS 0x00000400 ++#define AMD_MOUNT_TYPE_JFS 0x00000800 ++#define AMD_MOUNT_TYPE_CACHEFS 0x00001000 ++#define AMD_MOUNT_TYPE_CDFS 0x00002000 + #define AMD_MOUNT_TYPE_MASK 0x0000ffff + + #define AMD_ENTRY_CUT 0x00010000 +diff --git a/lib/defaults.c b/lib/defaults.c +index bdaba67..3fa2216 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -136,6 +136,7 @@ + #define NAME_AMD_UMOUNT_ON_EXIT "unmount_on_exit" + #define NAME_AMD_USE_TCPWRAPPERS "use_tcpwrappers" + #define NAME_AMD_VENDOR "vendor" ++#define NAME_AMD_LINUX_UFS_MOUNT_TYPE "linux_ufs_mount_type" + + /* Status returns */ + #define CFG_OK 0x0000 +@@ -543,6 +544,10 @@ static int conf_load_amd_defaults(void) + if (ret == CFG_FAIL) + goto error; + ++ ret = conf_update(sec, NAME_AMD_LINUX_UFS_MOUNT_TYPE, ++ DEFAULT_AMD_LINUX_UFS_MOUNT_TYPE, CONF_NONE); ++ if (ret == CFG_FAIL) ++ goto error; + return 1; + + error: +@@ -1706,6 +1711,11 @@ unsigned int conf_amd_get_dismount_interval(const char *section) + return (unsigned int) tmp; + } + ++char *conf_amd_get_linux_ufs_mount_type(void) ++{ ++ return conf_get_string(amd_gbl_sec, NAME_AMD_LINUX_UFS_MOUNT_TYPE); ++} ++ + unsigned long conf_amd_get_flags(const char *section) + { + const char *amd = amd_gbl_sec; +diff --git a/man/autofs.conf.5.in b/man/autofs.conf.5.in +index f25a918..c959b52 100644 +--- a/man/autofs.conf.5.in ++++ b/man/autofs.conf.5.in +@@ -390,6 +390,15 @@ LDAP URIs. + .B hesiod_base + .br + Sets the base name used for hesiod map sources. ++.TP ++.B linux_ufs_mount_type ++.br ++This is an aditional configuration option for the autofs amd format ++parser implementation. ++ ++There's no simple way to determine what the system default filesystem ++is and am-utils needs to be continually updated to do this and can ++easily get it wrong ayway. So allow it to be set in the configuration. + .SH EXAMPLE + .sp + .RS +.2i +diff --git a/modules/amd_parse.y b/modules/amd_parse.y +index 87e3309..8174fb2 100644 +--- a/modules/amd_parse.y ++++ b/modules/amd_parse.y +@@ -269,6 +269,9 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE + !strcmp($3, "ext4")) { + entry.flags |= AMD_MOUNT_TYPE_EXT; + entry.type = amd_strdup($3); ++ } else if (!strcmp($3, "ufs")) { ++ entry.flags |= AMD_MOUNT_TYPE_UFS; ++ entry.type = conf_amd_get_linux_ufs_mount_type(); + } else if (!strcmp($3, "cdfs")) { + entry.flags |= AMD_MOUNT_TYPE_CDFS; + entry.type = amd_strdup("iso9660"); +diff --git a/modules/amd_tok.l b/modules/amd_tok.l +index 10b1963..618bc91 100644 +--- a/modules/amd_tok.l ++++ b/modules/amd_tok.l +@@ -99,7 +99,7 @@ MNTOPT (opts|addopts|remopts) + FSOPTS (rhost|rfs|dev|cachedir|mount|unmount|umount|delay) + CHEOPT (mapdefault|none|inc|re|regexp|all) + MAPTYPE (file|nis|nisplus|ldap|hesiod|exec|ndbm|passwd|union) +-FSTYPE_LOCAL (link|linkx|lofs|ext2|ext3|ext4|xfs|jfs|cdfs|cachefs) ++FSTYPE_LOCAL (link|linkx|lofs|ufs|ext2|ext3|ext4|xfs|jfs|cdfs|cachefs) + FSTYPE_NET (nfs|nfsx|nfsl|host) + FSTYPE (auto|program|direct|lustre|{FSTYPE_LOCAL}|{FSTYPE_NET}) + +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 790f25e..0c708e6 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -1245,6 +1245,22 @@ static unsigned int validate_generic_options(unsigned int logopt, + return 1; + } + ++static unsigned int validate_ufs_fstype(unsigned int logopt, ++ struct amd_entry *entry) ++{ ++ const char *type = (const char *) entry->type; ++ ++ if (strcmp(type, "ext") && strcmp(type, "ext2") && ++ strcmp(type, "ext3") && strcmp(type, "ext4") && ++ strcmp(type, "xfs") && strcmp(type, "jfs")) { ++ error(logopt, MODPREFIX ++ "%s: mount type %s not valid as ufs mount type on Linux", ++ type); ++ return 0; ++ } ++ return 1; ++} ++ + static unsigned int validate_host_options(unsigned int logopt, + struct amd_entry *entry) + { +@@ -1282,6 +1298,11 @@ static int amd_mount(struct autofs_point *ap, const char *name, + ret = do_generic_mount(ap, name, entry, entry->rfs, flags); + break; + ++ case AMD_MOUNT_TYPE_UFS: ++ if (!validate_ufs_fstype(ap->logopt, entry)) ++ return 1; ++ /* fall through to validate generic options */ ++ + case AMD_MOUNT_TYPE_EXT: + case AMD_MOUNT_TYPE_XFS: + case AMD_MOUNT_TYPE_CDFS: +diff --git a/redhat/autofs.conf.default.in b/redhat/autofs.conf.default.in +index 1fa951b..8ccd5d6 100644 +--- a/redhat/autofs.conf.default.in ++++ b/redhat/autofs.conf.default.in +@@ -306,6 +306,15 @@ mount_nfs_default_protocol = 4 + # + # hesiod_base - the base name used for hesiod map sources. + # ++# Additional configuration options added: ++# ++# linux_ufs_mount_type - set the default system filesystem type that's ++# used for mount type ufs. There's no simple way to determine ++# what the system default filesystem is and am-utils needs to ++# be continually updated to do this and can easily get it wrong ++# anyway. ++# ++# + # Define global options for the amd parser within autofs. + # + [ amd ] +diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in +index 7a84566..934e411 100644 +--- a/samples/autofs.conf.default.in ++++ b/samples/autofs.conf.default.in +@@ -305,6 +305,15 @@ browse_mode = no + # + # hesiod_base - the base name used for hesiod map sources. + # ++# Additional configuration options added: ++# ++# linux_ufs_mount_type - set the default system filesystem type that's ++# used for mount type ufs. There's no simple way to determine ++# what the system default filesystem is and am-utils needs to ++# be continually updated to do this and can easily get it wrong ++# anyway. ++# ++# + # Define global options for the amd parser within autofs. + # + [ amd ] diff --git a/SOURCES/autofs-5.0.9-amd-lookup-allow-exec-to-be-used-by-amd-maps-in-master-map.patch b/SOURCES/autofs-5.0.9-amd-lookup-allow-exec-to-be-used-by-amd-maps-in-master-map.patch new file mode 100644 index 0000000..f6979d4 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-allow-exec-to-be-used-by-amd-maps-in-master-map.patch @@ -0,0 +1,81 @@ +autofs-5.0.9 - amd lookup allow amd maps to use exec in master map + +From: Ian Kent + +Amd uses the keyword exec for program maps (as it has a program mount +type). Allow the use of the exec keyword to be used for executable +maps in amd format master map entries. So just allow the keyword exec +to be used as a synonym of program for both sun and amd format map +entries since exec isn't otherwise used in master map entries. +--- + lib/master_parse.y | 15 ++++++++++++--- + lib/master_tok.l | 2 +- + man/auto.master.5.in | 2 ++ + 3 files changed, 15 insertions(+), 4 deletions(-) + +diff --git a/lib/master_parse.y b/lib/master_parse.y +index 03aedf7..e31023d 100644 +--- a/lib/master_parse.y ++++ b/lib/master_parse.y +@@ -329,7 +329,10 @@ map: PATH + if ((tmp = strchr($1, ','))) + *tmp++ = '\0'; + +- type = master_strdup($1); ++ if (strcmp($1, "exec")) ++ type = master_strdup($1); ++ else ++ type = master_strdup("program"); + if (!type) { + master_error("memory allocation error"); + local_free_vars(); +@@ -360,7 +363,10 @@ map: PATH + if ((tmp = strchr($1, ','))) + *tmp++ = '\0'; + +- type = master_strdup($1); ++ if (strcmp($1, "exec")) ++ type = master_strdup($1); ++ else ++ type = master_strdup("program"); + if (!type) { + master_error("memory allocation error"); + local_free_vars(); +@@ -391,7 +397,10 @@ map: PATH + if ((tmp = strchr($1, ','))) + *tmp++ = '\0'; + +- type = master_strdup($1); ++ if (strcmp($1, "exec")) ++ type = master_strdup($1); ++ else ++ type = master_strdup("program"); + if (!type) { + master_error("memory allocation error"); + local_free_vars(); +diff --git a/lib/master_tok.l b/lib/master_tok.l +index d43c1dd..9ba53f6 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -119,7 +119,7 @@ DNNAMESTR2 ([[:alnum:]_.\-]+) + INTMAP (-hosts|-null) + MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS})) + MULTISEP ([\-]{2}[[:blank:]]+) +-MTYPE ((file|program|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS})) ++MTYPE ((file|program|exec|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS})) + + + OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) +diff --git a/man/auto.master.5.in b/man/auto.master.5.in +index 2267550..83be83c 100644 +--- a/man/auto.master.5.in ++++ b/man/auto.master.5.in +@@ -93,6 +93,8 @@ The map is a regular text file. + .B program + The map is an executable program, which is passed a key on the command + line and returns an entry (everything besides the key) on stdout if successful. ++Optinally, the keyword exec may be used as a synonym for program to avoid ++confusion with amd formated maps mount type program. + .TP + .B yp + The map is a NIS (YP) database. diff --git a/SOURCES/autofs-5.0.9-amd-lookup-check-for-required-options-for-mounts.patch b/SOURCES/autofs-5.0.9-amd-lookup-check-for-required-options-for-mounts.patch new file mode 100644 index 0000000..2c38f48 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-check-for-required-options-for-mounts.patch @@ -0,0 +1,173 @@ +autofs-5.0.9 - amd lookup check for required options for mounts + +From: Ian Kent + + +--- + modules/parse_amd.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 101 insertions(+), 2 deletions(-) + +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 2056ed9..bc53b1d 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -1070,7 +1070,7 @@ static int do_nfsl_mount(struct autofs_point *ap, const char *name, + + static int wait_for_expire(struct autofs_point *ap) + { +- int ret = 1; ++ int ret = 0; + + st_wait_task(ap, ST_EXPIRE, 0); + +@@ -1078,7 +1078,7 @@ static int wait_for_expire(struct autofs_point *ap) + if (ap->state != ST_SHUTDOWN && + ap->state != ST_SHUTDOWN_PENDING && + ap->state != ST_SHUTDOWN_FORCE) { +- ret = 0; ++ ret = 1; + } + st_mutex_unlock(); + +@@ -1181,6 +1181,88 @@ out: + return ret; + } + ++static unsigned int validate_auto_options(unsigned int logopt, ++ struct amd_entry *entry) ++{ ++ /* ++ * The amd manual implies all the mount type auto options ++ * are optional but I don't think there's much point if ++ * no map is given. ++ */ ++ if (!entry->fs) { ++ error(logopt, MODPREFIX ++ "%s: file system not given", entry->type); ++ return 0; ++ } ++ return 1; ++} ++ ++static unsigned int validate_link_options(unsigned int logopt, ++ struct amd_entry *entry) ++{ ++ /* fs is the destimation of the link */ ++ return validate_auto_options(logopt, entry); ++} ++ ++static unsigned int validate_nfs_options(unsigned int logopt, ++ struct amd_entry *entry) ++{ ++ /* ++ * Required option rhost will always have a value. ++ * It is set from ${host} if it is found to be NULL ++ * earlier in the parsing process. ++ */ ++ if (!entry->rfs) { ++ if (entry->fs) ++ entry->rfs = strdup(entry->fs); ++ if (!entry->rfs) { ++ error(logopt, MODPREFIX ++ "%s: remote file system not given", entry->type); ++ return 0; ++ } ++ } ++ return 1; ++} ++ ++static unsigned int validate_generic_options(unsigned int logopt, ++ unsigned long fstype, ++ struct amd_entry *entry) ++{ ++ if (fstype != AMD_MOUNT_TYPE_LOFS) { ++ if (!entry->dev) { ++ error(logopt, MODPREFIX ++ "%s: mount device not given", entry->type); ++ return 0; ++ } ++ } else { ++ if (!entry->rfs) { ++ /* ++ * Can't use entry->type as the mount type to reprot ++ * the error since entry->type == "bind" not "lofs". ++ */ ++ error(logopt, "lofs: mount device not given"); ++ return 0; ++ } ++ } ++ return 1; ++} ++ ++static unsigned int validate_host_options(unsigned int logopt, ++ struct amd_entry *entry) ++{ ++ /* ++ * Not really that useful since rhost is always non-null ++ * because it will have the the value of the host name if ++ * it isn't set in the map entry. ++ */ ++ if (!entry->rhost) { ++ error(logopt, MODPREFIX ++ "%s: remote host name not given", entry->type); ++ return 0; ++ } ++ return 1; ++} ++ + static int amd_mount(struct autofs_point *ap, const char *name, + struct amd_entry *entry, struct map_source *source, + struct substvar *sv, unsigned int flags, +@@ -1191,35 +1273,52 @@ static int amd_mount(struct autofs_point *ap, const char *name, + + switch (fstype) { + case AMD_MOUNT_TYPE_AUTO: ++ if (!validate_auto_options(ap->logopt, entry)) ++ return 1; + ret = do_auto_mount(ap, name, entry, flags); + break; + + case AMD_MOUNT_TYPE_LOFS: ++ if (!validate_generic_options(ap->logopt, fstype, entry)) ++ return 1; + ret = do_generic_mount(ap, name, entry, entry->rfs, flags); + break; + + case AMD_MOUNT_TYPE_EXT: + case AMD_MOUNT_TYPE_XFS: ++ if (!validate_generic_options(ap->logopt, fstype, entry)) ++ return 1; + ret = do_generic_mount(ap, name, entry, entry->dev, flags); + break; + + case AMD_MOUNT_TYPE_NFS: ++ if (!validate_nfs_options(ap->logopt, entry)) ++ return 1; + ret = do_nfs_mount(ap, name, entry, flags); + break; + + case AMD_MOUNT_TYPE_NFSL: ++ if (!validate_nfs_options(ap->logopt, entry) || ++ !validate_link_options(ap->logopt, entry)) ++ return 1; + ret = do_nfsl_mount(ap, name, entry, sv, flags); + break; + + case AMD_MOUNT_TYPE_LINK: ++ if (!validate_link_options(ap->logopt, entry)) ++ return 1; + ret = do_link_mount(ap, name, entry, flags); + break; + + case AMD_MOUNT_TYPE_LINKX: ++ if (!validate_link_options(ap->logopt, entry)) ++ return 1; + ret = do_linkx_mount(ap, name, entry, flags); + break; + + case AMD_MOUNT_TYPE_HOST: ++ if (!validate_host_options(ap->logopt, entry)) ++ return 1; + ret = do_host_mount(ap, name, entry, source, flags); + break; + diff --git a/SOURCES/autofs-5.0.9-amd-lookup-dont-umount-admin-mounted-external-mounts.patch b/SOURCES/autofs-5.0.9-amd-lookup-dont-umount-admin-mounted-external-mounts.patch new file mode 100644 index 0000000..3723747 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-dont-umount-admin-mounted-external-mounts.patch @@ -0,0 +1,112 @@ +autofs-5.0.9 - amd lookup dont umount admin mounted external mounts + +From: Ian Kent + +If an autofs doesn't mount an external mount then it shouldn't +umount it. +--- + include/mounts.h | 2 +- + lib/mounts.c | 7 +++++-- + modules/parse_amd.c | 8 ++++++-- + 3 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/include/mounts.h b/include/mounts.h +index 07a8c3b..17cae31 100644 +--- a/include/mounts.h ++++ b/include/mounts.h +@@ -101,7 +101,7 @@ unsigned int get_kver_major(void); + unsigned int get_kver_minor(void); + char *make_options_string(char *path, int kernel_pipefd, const char *extra); + char *make_mnt_name_string(char *path); +-int ext_mount_add(struct list_head *, const char *); ++int ext_mount_add(struct list_head *, const char *, unsigned int); + int ext_mount_remove(struct list_head *, const char *); + struct mnt_list *get_mnt_list(const char *table, const char *path, int include); + struct mnt_list *reverse_mnt_list(struct mnt_list *list); +diff --git a/lib/mounts.c b/lib/mounts.c +index d8357d0..c9e1237 100644 +--- a/lib/mounts.c ++++ b/lib/mounts.c +@@ -51,6 +51,7 @@ static const char kver_options_template[] = "fd=%d,pgrp=%u,minproto=3,maxproto= + + struct ext_mount { + char *mountpoint; ++ unsigned int umount; + struct list_head mount; + struct list_head mounts; + }; +@@ -619,7 +620,7 @@ static struct ext_mount *ext_mount_lookup(const char *mountpoint) + return NULL; + } + +-int ext_mount_add(struct list_head *entry, const char *path) ++int ext_mount_add(struct list_head *entry, const char *path, unsigned int umount) + { + struct ext_mount *em; + char *auto_dir; +@@ -661,6 +662,7 @@ int ext_mount_add(struct list_head *entry, const char *path) + ret = -1; + goto done; + } ++ em->umount = umount; + INIT_LIST_HEAD(&em->mount); + INIT_LIST_HEAD(&em->mounts); + +@@ -701,11 +703,12 @@ int ext_mount_remove(struct list_head *entry, const char *path) + goto done; + else { + list_del_init(&em->mount); ++ if (em->umount) ++ ret = 1; + if (list_empty(&em->mount)) { + free(em->mountpoint); + free(em); + } +- ret = 1; + } + done: + pthread_mutex_unlock(&ext_mount_hash_mutex); +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index fa0f75d..bc056a7 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -978,6 +978,7 @@ static int do_generic_mount(struct autofs_point *ap, const char *name, + struct amd_entry *entry, const char *target, + unsigned int flags) + { ++ unsigned int umount = 0; + int ret = 0; + + if (!entry->sublink) { +@@ -994,9 +995,10 @@ static int do_generic_mount(struct autofs_point *ap, const char *name, + target, entry->type, entry->opts); + if (ret) + goto out; ++ umount = 1; + } + /* We might be using an external mount */ +- ext_mount_add(&entry->ext_mount, entry->fs); ++ ext_mount_add(&entry->ext_mount, entry->fs, umount); + ret = do_link_mount(ap, name, entry, flags); + } + out: +@@ -1009,6 +1011,7 @@ static int do_nfs_mount(struct autofs_point *ap, const char *name, + char target[PATH_MAX + 1]; + unsigned int proximity; + char *opts = entry->opts; ++ unsigned int umount = 0; + int ret = 0; + + strcpy(target, entry->rhost); +@@ -1030,9 +1033,10 @@ static int do_nfs_mount(struct autofs_point *ap, const char *name, + mount_nfs->context); + if (ret) + goto out; ++ umount = 1; + } + /* We might be using an external mount */ +- ext_mount_add(&entry->ext_mount, entry->fs); ++ ext_mount_add(&entry->ext_mount, entry->fs, umount); + ret = do_link_mount(ap, name, entry, flags); + } + out: diff --git a/SOURCES/autofs-5.0.9-amd-lookup-fix-amd-entry-not-found-at-expire.patch b/SOURCES/autofs-5.0.9-amd-lookup-fix-amd-entry-not-found-at-expire.patch new file mode 100644 index 0000000..116a99b --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-fix-amd-entry-not-found-at-expire.patch @@ -0,0 +1,44 @@ +autofs-5.0.9 - fix amd entry not found at expire + +From: Ian Kent + +Due to the way amd matches keys in its map it's possible that +distinct key entries aren't present in the map. + +The indirect mount expire procedure needs to lookup cache entries +for offset mounts in order to get the control file handle needed +to send an expire check to them. + +So we need to make sure that when a distinct match isn't found +an expire check is still done. That's OK because the mounts in +the expire list are under the autofs directory so they should +be checked and the ap control file handle can be used for it. +--- + daemon/indirect.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/daemon/indirect.c b/daemon/indirect.c +index 6dfbd25..a04a624 100644 +--- a/daemon/indirect.c ++++ b/daemon/indirect.c +@@ -513,15 +513,13 @@ void *expire_proc_indirect(void *arg) + if (!me && ind_key) + me = lookup_source_mapent(ap, ind_key, LKP_NORMAL); + pthread_cleanup_pop(1); +- if (!me) +- continue; + +- if (*me->key == '/') { +- ioctlfd = me->ioctlfd; +- } else { +- ioctlfd = ap->ioctlfd; ++ ioctlfd = ap->ioctlfd; ++ if (me) { ++ if (*me->key == '/') ++ ioctlfd = me->ioctlfd; ++ cache_unlock(me->mc); + } +- cache_unlock(me->mc); + + debug(ap->logopt, "expire %s", next->path); + diff --git a/SOURCES/autofs-5.0.9-amd-lookup-fix-autofs_use_lofs-value-in-config.patch b/SOURCES/autofs-5.0.9-amd-lookup-fix-autofs_use_lofs-value-in-config.patch new file mode 100644 index 0000000..30827b4 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-fix-autofs_use_lofs-value-in-config.patch @@ -0,0 +1,37 @@ +autofs-5.0.9 - amd lookup fix autofs_use_lofs value in config + +From: Ian Kent + +The commented out setting in autofs.conf does not reflect its default +value. +--- + redhat/autofs.conf.default.in | 2 +- + samples/autofs.conf.default.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/redhat/autofs.conf.default.in b/redhat/autofs.conf.default.in +index 8b04617..1fa951b 100644 +--- a/redhat/autofs.conf.default.in ++++ b/redhat/autofs.conf.default.in +@@ -325,7 +325,7 @@ dismount_interval = 300 + # appears to work reasonably well most of the time without the + # update). + # +-# autofs_use_lofs = no ++# autofs_use_lofs = yes + # + # Several configuration options can be set per mount point. + # In particulr map_type, map_name, map_defaults, search_path, +diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in +index d0a2002..7a84566 100644 +--- a/samples/autofs.conf.default.in ++++ b/samples/autofs.conf.default.in +@@ -324,7 +324,7 @@ dismount_interval = 300 + # appears to work reasonably well most of the time without the + # update). + # +-# autofs_use_lofs = no ++# autofs_use_lofs = yes + # + # Several configuration options can be set per mount point. + # In particulr map_type, map_name, map_defaults, search_path, diff --git a/SOURCES/autofs-5.0.9-amd-lookup-fix-expire-of-amd-nfs-mounts.patch b/SOURCES/autofs-5.0.9-amd-lookup-fix-expire-of-amd-nfs-mounts.patch new file mode 100644 index 0000000..ad794c3 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-fix-expire-of-amd-nfs-mounts.patch @@ -0,0 +1,67 @@ +autofs-5.0.9 - amd lookup fix expire of amd nfs mounts + +From: Ian Kent + +Becuase of the way map entries are matched for amd maps there +might not be an entry in the map entry cache for mounts. This +was causing mounts to not expire. +--- + daemon/automount.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/daemon/automount.c b/daemon/automount.c +index 0ba3580..9d9ba7b 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -462,7 +462,7 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi + { + struct mapent_cache *mc; + struct mapent *me; +- unsigned int is_mm_root; ++ unsigned int is_mm_root = 0; + int left; + + me = lookup_source_mapent(ap, path, LKP_DISTINCT); +@@ -474,22 +474,22 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi + ind_key++; + + me = lookup_source_mapent(ap, ind_key, LKP_NORMAL); +- if (!me) +- return 0; + } + +- mc = me->mc; +- is_mm_root = (me->multi == me); ++ if (me) { ++ mc = me->mc; ++ is_mm_root = (me->multi == me); ++ } + + left = 0; + +- pthread_cleanup_push(cache_lock_cleanup, mc); +- +- if (me->multi) { ++ if (me && me->multi) { + char root[PATH_MAX]; + char *base; + int cur_state; + ++ pthread_cleanup_push(cache_lock_cleanup, mc); ++ + if (!strchr(me->multi->key, '/')) + /* Indirect multi-mount root */ + /* sprintf okay - if it's mounted, it's +@@ -516,9 +516,11 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi + (ap->entry->maps->flags & MAP_FLAG_FORMAT_AMD)) + cache_pop_mapent(me); + pthread_setcancelstate(cur_state, NULL); ++ pthread_cleanup_pop(0); + } + +- pthread_cleanup_pop(1); ++ if (me) ++ cache_unlock(mc); + + if (left || is_autofs_fs) + return left; diff --git a/SOURCES/autofs-5.0.9-amd-lookup-fix-expire-of-external-mounts.patch b/SOURCES/autofs-5.0.9-amd-lookup-fix-expire-of-external-mounts.patch new file mode 100644 index 0000000..5b3af25 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-fix-expire-of-external-mounts.patch @@ -0,0 +1,33 @@ +autofs-5.0.9 - amd lookup fix expire of external mounts + +From: Ian Kent + +When expiring a submount it's necessary to ensure that any triggers +that may have been mounted over the top of the submount by its parent +are umounted so umount_subtree_mounts() is called with the parent ap. + +But this can lead to an out of order umount. So far this hasn't been +a problem but if this happens when expiring an amd mount that refers +to an external mount the amd mount structure can't be found (since +we are looking in the parent ap) and subsequently the external mount +doesn't get checked and umounted. + +So restrict the call to umount_subtree_mounts() to umount only offset +mounts by passing is_autofs_fs as 1 always. +--- + daemon/automount.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/daemon/automount.c b/daemon/automount.c +index 9d9ba7b..a6a9321 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -628,7 +628,7 @@ int umount_multi(struct autofs_point *ap, const char *path, int incl) + * parent may have mounted over top of us. + */ + if (ap->submount) +- left += umount_subtree_mounts(ap->parent, path, is_autofs_fs); ++ left += umount_subtree_mounts(ap->parent, path, 1); + + left += umount_subtree_mounts(ap, path, is_autofs_fs); + diff --git a/SOURCES/autofs-5.0.9-amd-lookup-fix-host-mount-lookup.patch b/SOURCES/autofs-5.0.9-amd-lookup-fix-host-mount-lookup.patch new file mode 100644 index 0000000..9478552 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-fix-host-mount-lookup.patch @@ -0,0 +1,173 @@ +autofs-5.0.9 - amd lookup fix host mount lookup + +From: Ian Kent + +The amd host mount type is implemented by using the autofs internal +hosts map module and the autofs sun parser. + +When using the amd mount type host we need to avoid calling back +into the lookup module of the amd map (as an amd format lookup) +since the lookup keys for mounts in the tree might not match +correctly. In any case it's a call into a lookup module that +isn't needed. +--- + daemon/lookup.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + modules/parse_amd.c | 34 +++++++++++++++++++++++---- + 2 files changed, 94 insertions(+), 5 deletions(-) + +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -795,6 +795,62 @@ int do_lookup_mount(struct autofs_point + return status; + } + ++static int lookup_amd_instance(struct autofs_point *ap, ++ struct map_source *map, ++ const char *name, int name_len) ++{ ++ struct map_source *instance; ++ struct amd_entry *entry; ++ const char *argv[2]; ++ const char **pargv = NULL; ++ int argc = 0; ++ struct mapent *me; ++ char *m_key; ++ ++ me = cache_lookup_distinct(map->mc, name); ++ if (!me || !me->multi) { ++ error(ap->logopt, "expected multi mount entry not found"); ++ return NSS_STATUS_UNKNOWN; ++ } ++ ++ m_key = malloc(strlen(ap->path) + strlen(me->multi->key) + 1); ++ if (!m_key) { ++ error(ap->logopt, "failed to allocate storage for search key"); ++ return NSS_STATUS_UNKNOWN; ++ } ++ ++ strcpy(m_key, ap->path); ++ strcat(m_key, "/"); ++ strcat(m_key, me->multi->key); ++ entry = master_find_amdmount(ap, m_key); ++ if (!entry) { ++ error(ap->logopt, "expected amd mount entry not found"); ++ free(m_key); ++ return NSS_STATUS_UNKNOWN; ++ } ++ free(m_key); ++ ++ if (strcmp(entry->type, "host")) { ++ error(ap->logopt, "unexpected map type %s", entry->type); ++ return NSS_STATUS_UNKNOWN; ++ } ++ ++ if (entry->opts) { ++ argv[0] = entry->opts; ++ argv[1] = NULL; ++ pargv = argv; ++ argc = 1; ++ } ++ ++ instance = master_find_source_instance(map, "hosts", "sun", argc, pargv); ++ if (!instance) { ++ error(ap->logopt, "expected hosts map instance not found"); ++ return NSS_STATUS_UNKNOWN; ++ } ++ ++ return do_lookup_mount(ap, instance, name, name_len); ++} ++ + static int lookup_name_file_source_instance(struct autofs_point *ap, struct map_source *map, const char *name, int name_len) + { + struct map_source *instance; +@@ -804,6 +860,9 @@ static int lookup_name_file_source_insta + struct stat st; + char *type, *format; + ++ if (*name == '/' && map->flags & MAP_FLAG_FORMAT_AMD) ++ return lookup_amd_instance(ap, map, name, name_len); ++ + if (stat(map->argv[0], &st) == -1) { + debug(ap->logopt, "file map not found"); + return NSS_STATUS_NOTFOUND; +@@ -839,6 +898,9 @@ static int lookup_name_source_instance(s + const char *format; + time_t age = time(NULL); + ++ if (*name == '/' && map->flags & MAP_FLAG_FORMAT_AMD) ++ return lookup_amd_instance(ap, map, name, name_len); ++ + format = map->format; + + instance = master_find_source_instance(map, type, format, 0, NULL); +@@ -867,6 +929,9 @@ static int do_name_lookup_mount(struct a + return NSS_STATUS_UNKNOWN; + } + ++ if (*name == '/' && map->flags & MAP_FLAG_FORMAT_AMD) ++ return lookup_amd_instance(ap, map, name, name_len); ++ + /* + * This is only called when map->type != NULL. + * We only need to look for a map if source type is +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -1073,29 +1073,53 @@ static int do_host_mount(struct autofs_p + unsigned int flags) + { + struct lookup_mod *lookup; ++ struct map_source *instance; + struct mapent *me; + const char *argv[2]; ++ const char **pargv = NULL; ++ int argc = 0; + int ret = 1; + +- argv[0] = entry->opts; +- argv[1] = NULL; ++ if (entry->opts) { ++ argv[0] = entry->opts; ++ argv[1] = NULL; ++ pargv = argv; ++ argc = 1; ++ } + +- lookup = open_lookup("hosts", MODPREFIX, NULL, 1, argv); ++ instance_mutex_lock(); ++ lookup = open_lookup("hosts", MODPREFIX, NULL, argc, pargv); + if (!lookup) { + debug(ap->logopt, "open lookup module hosts failed"); ++ instance_mutex_unlock(); + goto out; + } + ++ instance = master_find_source_instance(source, "hosts", "sun", argc, pargv); ++ if (!instance) { ++ instance = master_add_source_instance(source, ++ "hosts", "sun", time(NULL), argc, pargv); ++ if (!instance) { ++ error(ap->logopt, MODPREFIX ++ "failed to create source instance for hosts map"); ++ instance_mutex_unlock(); ++ close_lookup(lookup); ++ goto out; ++ } ++ } ++ instance->lookup = lookup; ++ instance_mutex_unlock(); ++ ++ cache_writelock(source->mc); + me = cache_lookup_distinct(source->mc, name); + if (me) + cache_push_mapent(me, NULL); ++ cache_unlock(source->mc); + + master_source_current_wait(ap->entry); + ap->entry->current = source; + + ret = lookup->lookup_mount(ap, name, strlen(name), lookup->context); +- +- close_lookup(lookup); + out: + return ret; + } diff --git a/SOURCES/autofs-5.0.9-amd-lookup-fix-host-mount-naming.patch b/SOURCES/autofs-5.0.9-amd-lookup-fix-host-mount-naming.patch new file mode 100644 index 0000000..e38cd0c --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-fix-host-mount-naming.patch @@ -0,0 +1,213 @@ +autofs-5.0.9 - amd lookup fix host mount naming + +From: Ian Kent + +Currently the amd host mount type assumes the lookup name is +the host name for the host mount but amd uses ${rhost} for +this. + +This introduces the possibility of multiple concurrent mount +requests since constructing a mount tree that isn't under the +lookup name can't take advantage of the kernel queuing other +concurrent lookups while the mount tree is constructed. +--- + daemon/lookup.c | 20 +++++++++++++---- + modules/parse_amd.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++-- + modules/parse_sun.c | 22 +++++++++++------- + 3 files changed, 89 insertions(+), 14 deletions(-) + +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -815,7 +815,8 @@ static int lookup_amd_instance(struct au + + m_key = malloc(strlen(ap->path) + strlen(me->multi->key) + 1); + if (!m_key) { +- error(ap->logopt, "failed to allocate storage for search key"); ++ error(ap->logopt, ++ "failed to allocate storage for search key"); + return NSS_STATUS_UNKNOWN; + } + +@@ -823,12 +824,12 @@ static int lookup_amd_instance(struct au + strcat(m_key, "/"); + strcat(m_key, me->multi->key); + entry = master_find_amdmount(ap, m_key); ++ free(m_key); ++ + if (!entry) { + error(ap->logopt, "expected amd mount entry not found"); +- free(m_key); + return NSS_STATUS_UNKNOWN; + } +- free(m_key); + + if (strcmp(entry->type, "host")) { + error(ap->logopt, "unexpected map type %s", entry->type); +@@ -843,6 +844,17 @@ static int lookup_amd_instance(struct au + } + + instance = master_find_source_instance(map, "hosts", "sun", argc, pargv); ++ /* If this is an nss map instance it may have an amd host map sub instance */ ++ if (!instance && map->instance) { ++ struct map_source *next = map->instance; ++ while (next) { ++ instance = master_find_source_instance(next, ++ "hosts", "sun", argc, pargv); ++ if (instance) ++ break; ++ next = next->next; ++ } ++ } + if (!instance) { + error(ap->logopt, "expected hosts map instance not found"); + return NSS_STATUS_UNKNOWN; +@@ -1174,7 +1186,6 @@ int lookup_nss_mount(struct autofs_point + } + if (ap->state != ST_INIT) + send_map_update_request(ap); +- pthread_cleanup_pop(1); + + /* + * The last source lookup will return NSS_STATUS_NOTFOUND if the +@@ -1183,6 +1194,7 @@ int lookup_nss_mount(struct autofs_point + */ + if (result == NSS_STATUS_NOTFOUND || result == NSS_STATUS_UNAVAIL) + update_negative_cache(ap, source, name); ++ pthread_cleanup_pop(1); + + return !result; + } +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -1068,6 +1068,23 @@ static int do_nfsl_mount(struct autofs_p + return do_link_mount(ap, name, entry, flags); + } + ++static int wait_for_expire(struct autofs_point *ap) ++{ ++ int ret = 1; ++ ++ st_wait_task(ap, ST_EXPIRE, 0); ++ ++ st_mutex_lock(); ++ if (ap->state != ST_SHUTDOWN && ++ ap->state != ST_SHUTDOWN_PENDING && ++ ap->state != ST_SHUTDOWN_FORCE) { ++ ret = 0; ++ } ++ st_mutex_unlock(); ++ ++ return ret; ++} ++ + static int do_host_mount(struct autofs_point *ap, const char *name, + struct amd_entry *entry, struct map_source *source, + unsigned int flags) +@@ -1080,6 +1097,36 @@ static int do_host_mount(struct autofs_p + int argc = 0; + int ret = 1; + ++ /* ++ * If the mount point name isn't the same as the host name ++ * then we need to symlink to it after the mount. Attempt ++ * the allocation and set entry->path to the base location ++ * of the hosts mount tree so we can find it in ++ * lookup_nss_mount() later. ++ */ ++ if (strcmp(name, entry->rhost)) { ++ char *target; ++ size_t len = strlen(ap->path) + strlen(entry->rhost) + 2; ++ target = malloc(len); ++ if (!target) { ++ warn(ap->logopt, MODPREFIX ++ "failed to alloc target to hosts mount base"); ++ goto out; ++ } ++ strcpy(target, ap->path); ++ strcat(target, "/"); ++ strcat(target, entry->rhost); ++ if (entry->path) ++ free(entry->path); ++ entry->path = target; ++ /* ++ * Wait for any expire before racing to mount the ++ * export tree or bail out if we're shutting down. ++ */ ++ if (!wait_for_expire(ap)) ++ goto out; ++ } ++ + if (entry->opts) { + argv[0] = entry->opts; + argv[1] = NULL; +@@ -1095,7 +1142,8 @@ static int do_host_mount(struct autofs_p + goto out; + } + +- instance = master_find_source_instance(source, "hosts", "sun", argc, pargv); ++ instance = master_find_source_instance(source, ++ "hosts", "sun", argc, pargv); + if (!instance) { + instance = master_add_source_instance(source, + "hosts", "sun", time(NULL), argc, pargv); +@@ -1119,7 +1167,16 @@ static int do_host_mount(struct autofs_p + master_source_current_wait(ap->entry); + ap->entry->current = source; + +- ret = lookup->lookup_mount(ap, name, strlen(name), lookup->context); ++ ret = lookup->lookup_mount(ap, entry->rhost, ++ strlen(entry->rhost), lookup->context); ++ ++ if (!strcmp(name, entry->rhost)) ++ goto out; ++ ++ if (do_mount(ap, ap->path, ++ name, strlen(name), entry->path, "bind", "symlink")) ++ warn(ap->logopt, MODPREFIX ++ "failed to create symlink to hosts mount base"); + out: + return ret; + } +--- autofs-5.0.7.orig/modules/parse_sun.c ++++ autofs-5.0.7/modules/parse_sun.c +@@ -1343,26 +1343,32 @@ int parse_mount(struct autofs_point *ap, + strcat(m_root, name); + } + ++ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + cache_readlock(mc); + me = cache_lookup_distinct(mc, name); +- if (me) { +- /* So we know we're the multi-mount root */ +- if (!me->multi) +- me->multi = me; +- } +- + if (!me) { + free(options); + cache_unlock(mc); ++ pthread_setcancelstate(cur_state, NULL); + error(ap->logopt, + MODPREFIX "can't find multi root %s", name); + return 1; + } + ++ cache_multi_writelock(me); ++ /* Someone beat us to it, return success */ ++ if (me->multi) { ++ free(options); ++ cache_multi_unlock(me); ++ cache_unlock(mc); ++ pthread_setcancelstate(cur_state, NULL); ++ return 0; ++ } ++ /* So we know we're the multi-mount root */ ++ me->multi = me; ++ + age = me->age; + +- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); +- cache_multi_writelock(me); + /* It's a multi-mount; deal with it */ + do { + char *path, *myoptions, *loc; diff --git a/SOURCES/autofs-5.0.9-amd-lookup-fix-lofs-mounting.patch b/SOURCES/autofs-5.0.9-amd-lookup-fix-lofs-mounting.patch new file mode 100644 index 0000000..71ec18a --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-fix-lofs-mounting.patch @@ -0,0 +1,99 @@ +autofs-5.0.9 - amd lookup fix lofs mounting + +From: Ian Kent + +The kernel leaves mount type autofs alone because they are supposed +to be autofs sub-mounts and they look after their own expiration. So +mounts bound to an autofs submount won't ever be expired. +--- + daemon/spawn.c | 42 ++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 38 insertions(+), 4 deletions(-) + +diff --git a/daemon/spawn.c b/daemon/spawn.c +index a6c8c34..bfb8cfc 100644 +--- a/daemon/spawn.c ++++ b/daemon/spawn.c +@@ -111,6 +111,12 @@ static int timed_read(int pipe, char *buf, size_t len, int time) + return ret; + } + ++ if (pfd[0].fd == -1) ++ return 0; ++ ++ if ((pfd[0].revents & (POLLIN|POLLHUP)) == POLLHUP) ++ return 0; ++ + while ((ret = read(pipe, buf, len)) == -1 && errno == EINTR); + + return ret; +@@ -179,7 +185,8 @@ static int do_spawn(unsigned logopt, unsigned int wait, + * I hope host names are never allowed "/" as first char + */ + if (use_open && *(argv[loc]) == '/') { +- int fd; ++ char **p; ++ int is_bind, fd; + + pid_t pgrp = getpgrp(); + +@@ -209,6 +216,33 @@ static int do_spawn(unsigned logopt, unsigned int wait, + setegid(0); + if (pgrp >= 0) + setpgid(0, pgrp); ++ ++ /* ++ * The kernel leaves mount type autofs alone because ++ * they are supposed to be autofs sub-mounts and they ++ * look after their own expiration. So mounts bound ++ * to an autofs submount won't ever be expired. ++ */ ++ is_bind = 0; ++ p = (char **) argv; ++ while (*p) { ++ if (strcmp(*p, "--bind")) { ++ p++; ++ continue; ++ } ++ is_bind = 1; ++ break; ++ } ++ if (!is_bind) ++ goto done; ++ ++ if (is_mounted(_PROC_MOUNTS, argv[loc], MNTS_AUTOFS)) { ++ fprintf(stderr, ++ "error: can't bind to an autofs mount\n"); ++ close(STDOUT_FILENO); ++ close(STDERR_FILENO); ++ _exit(EINVAL); ++ } + } + done: + execv(prog, (char *const *) argv); +@@ -384,7 +418,7 @@ int spawn_mount(unsigned logopt, ...) + + while (retries--) { + ret = do_spawn(logopt, wait, options, prog, (const char **) argv); +- if (ret & MTAB_NOTUPDATED) { ++ if (ret == MTAB_NOTUPDATED) { + struct timespec tm = {3, 0}; + + /* +@@ -502,7 +536,7 @@ int spawn_bind_mount(unsigned logopt, ...) + + while (retries--) { + ret = do_spawn(logopt, -1, options, prog, (const char **) argv); +- if (ret & MTAB_NOTUPDATED) { ++ if (ret == MTAB_NOTUPDATED) { + struct timespec tm = {3, 0}; + + /* +@@ -604,7 +638,7 @@ int spawn_umount(unsigned logopt, ...) + + while (retries--) { + ret = do_spawn(logopt, wait, options, prog, (const char **) argv); +- if (ret & MTAB_NOTUPDATED) { ++ if (ret == MTAB_NOTUPDATED) { + /* + * If the mount succeeded but the mtab was not + * updated, then retry the umount just to update diff --git a/SOURCES/autofs-5.0.9-amd-lookup-fix-old-conf-handling.patch b/SOURCES/autofs-5.0.9-amd-lookup-fix-old-conf-handling.patch new file mode 100644 index 0000000..733305f --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-fix-old-conf-handling.patch @@ -0,0 +1,104 @@ +autofs-5.0.9 - amd lookup fix old conf handling + +From: Ian Kent + +When the configuration changed to using lower case option names +old configuration files with upper case names stopped working. + +This is because, for configuration option lookup the hash of +the option string always needs to be the same case, which was +overlooked at the time. + +Also fix a couple of other things, possible incorect return +from conf_update() what adding a new entry and change to using +isblank() instead of checking for a space only. +--- + lib/defaults.c | 27 +++++++++++++++++++++------ + 1 file changed, 21 insertions(+), 6 deletions(-) + +diff --git a/lib/defaults.c b/lib/defaults.c +index 3fa2216..7043dfc 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -43,6 +43,7 @@ + #define OLD_CONFIG_FILE AUTOFS_CONF_DIR "/autofs" + #define MAX_LINE_LEN 256 + #define MAX_SECTION_NAME MAX_LINE_LEN ++#define MAX_CFG_NAME_LEN 31 + + #define NAME_MASTER_MAP "master_map_name" + +@@ -661,7 +662,7 @@ static int conf_update(const char *section, + ret = CFG_FAIL; + co = conf_lookup(section, key); + if (!co) +- ret = conf_add(section, key, value, flags); ++ return conf_add(section, key, value, flags); + else { + char *val = NULL, *tmp = NULL; + /* Environment overrides file value */ +@@ -691,15 +692,29 @@ error: + return ret; + } + ++static u_int32_t get_hash(const char *key, unsigned int size) ++{ ++ const char *pkey = key; ++ char lkey[MAX_CFG_NAME_LEN]; ++ char *plkey = &lkey[0]; ++ ++ while (*pkey) ++ *plkey++ = tolower(*pkey++); ++ *plkey = '\0'; ++ return hash(lkey, size); ++} ++ + static struct conf_option *conf_lookup(const char *section, const char *key) + { + struct conf_option *co; ++ u_int32_t key_hash; + unsigned int size = CFG_TABLE_SIZE; + + if (!key || !section) + return NULL; + +- for (co = config->hash[hash(key, size)]; co != NULL; co = co->next) { ++ key_hash = get_hash(key, size); ++ for (co = config->hash[key_hash]; co != NULL; co = co->next) { + if (strcasecmp(section, co->section)) + continue; + if (!strcasecmp(key, co->name)) +@@ -772,7 +787,7 @@ static int parse_line(char *line, char **sec, char **res, char **value) + if (*key == '#' || (*key != '[' && !isalpha(*key))) + return 0; + +- while (*key && *key == ' ') ++ while (*key && isblank(*key)) + key++; + + if (!*key) +@@ -780,13 +795,13 @@ static int parse_line(char *line, char **sec, char **res, char **value) + + if (*key == '[') { + char *tmp; +- while (*key && (*key == '[' || *key == ' ')) ++ while (*key && (*key == '[' || isblank(*key))) + key++; + tmp = strchr(key, ']'); + if (!tmp) + return 0; + *tmp = ' '; +- while (*tmp && *tmp == ' ') { ++ while (*tmp && isblank(*tmp)) { + *tmp = '\0'; + tmp--; + } +@@ -803,7 +818,7 @@ static int parse_line(char *line, char **sec, char **res, char **value) + + *val++ = '\0'; + +- while (*(--tmp) == ' ') ++ while (isblank(*(--tmp))) + *tmp = '\0'; + + while (*val && (*val == '"' || isblank(*val))) diff --git a/SOURCES/autofs-5.0.9-amd-lookup-fix-prefix-not-set-on-mount-reconnect.patch b/SOURCES/autofs-5.0.9-amd-lookup-fix-prefix-not-set-on-mount-reconnect.patch new file mode 100644 index 0000000..3ef090b --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-fix-prefix-not-set-on-mount-reconnect.patch @@ -0,0 +1,101 @@ +autofs-5.0.9 - fix prefix not set on mount reconnect + +From: Ian Kent + +When autofs is started and there are pre-existing mounts the daemon +will attempt to reconnect to these mounts to reconstuct the mount +tree. + +This process is recursive so subordinate mounts can be reconstructed +before parent mounts complete reconnection. + +Also, amd subordinate mounts of type "auto" parent mounts may need +to use the parent mount prefix which was set post mount and wasn't +available. So, setting the parent mount prefix has to be done near +the beginning of parent mount operation. +--- + modules/mount_autofs.c | 8 ++++++++ + modules/parse_amd.c | 30 +++++++++++++----------------- + 2 files changed, 21 insertions(+), 17 deletions(-) + +diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c +index ab5a8e3..c7cba3a 100644 +--- a/modules/mount_autofs.c ++++ b/modules/mount_autofs.c +@@ -255,6 +255,14 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, + + mounts_mutex_lock(ap); + ++ if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ struct amd_entry *am_entry = __master_find_amdmount(ap, entry->path); ++ if (am_entry && am_entry->pref) { ++ nap->pref = am_entry->pref; ++ am_entry->pref = NULL; ++ } ++ } ++ + if (handle_mounts_startup_cond_init(&suc)) { + crit(ap->logopt, MODPREFIX + "failed to init startup cond for mount %s", entry->path); +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index bc056a7..410f6ff 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -893,7 +893,6 @@ static int do_auto_mount(struct autofs_point *ap, const char *name, + struct amd_entry *entry, unsigned int flags) + { + char target[PATH_MAX + 1]; +- int ret; + + if (!entry->map_type) + strcpy(target, entry->fs); +@@ -903,18 +902,8 @@ static int do_auto_mount(struct autofs_point *ap, const char *name, + strcat(target, entry->fs); + } + +- ret = do_mount(ap, ap->path, +- name, strlen(name), target, "autofs", NULL); +- if (!ret) { +- struct autofs_point *sm; +- sm = master_find_submount(ap, entry->path); +- if (sm) { +- sm->pref = entry->pref; +- entry->pref = NULL; +- } +- } +- +- return ret; ++ return do_mount(ap, ap->path, ++ name, strlen(name), target, "autofs", NULL); + } + + static int do_link_mount(struct autofs_point *ap, const char *name, +@@ -1878,17 +1867,24 @@ int parse_mount(struct autofs_point *ap, const char *name, + + dequote_entry(ap, this); + ++ /* ++ * Type "auto" needs to set the prefix at mount time so ++ * add parsed entry to parent amd mount list and remove ++ * on mount fail. ++ */ ++ mounts_mutex_lock(ap); ++ list_add_tail(&this->entries, &ap->amdmounts); ++ mounts_mutex_unlock(ap); ++ + rv = amd_mount(ap, name, this, source, sv, flags, ctxt); + mounts_mutex_lock(ap); + if (!rv) { +- /* Add to the parent list of mounts */ +- list_add_tail(&this->entries, &ap->amdmounts); +- /* Mounted, leave it on the parent list */ ++ /* Mounted, remove entry from parsed list */ + list_del_init(&this->list); + mounts_mutex_unlock(ap); + break; + } +- /* Not mounted, remove it from the parent list */ ++ /* Not mounted, remove entry from the parent list */ + list_del_init(&this->entries); + mounts_mutex_unlock(ap); + } diff --git a/SOURCES/autofs-5.0.9-amd-lookup-move-get_proximity-to-parse_subs-c.patch b/SOURCES/autofs-5.0.9-amd-lookup-move-get_proximity-to-parse_subs-c.patch new file mode 100644 index 0000000..4cd9058 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-move-get_proximity-to-parse_subs-c.patch @@ -0,0 +1,484 @@ +autofs-5.0.9 - amd lookup move get_proximity() to parse_subs.c + +From: Ian Kent + +Later we'll need to use get_proximity() from outside modules/replicated.c +so move it to the autofs library. +--- + include/parse_subs.h | 8 ++ + lib/parse_subs.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++ + modules/replicated.c | 197 ------------------------------------------------- + 3 files changed, 207 insertions(+), 197 deletions(-) + +diff --git a/include/parse_subs.h b/include/parse_subs.h +index ecc712d..c0da5ae 100644 +--- a/include/parse_subs.h ++++ b/include/parse_subs.h +@@ -18,6 +18,13 @@ + #ifndef PARSE_SUBS_H + #define PARSE_SUBS_H + ++#define PROXIMITY_ERROR 0x0000 ++#define PROXIMITY_LOCAL 0x0001 ++#define PROXIMITY_SUBNET 0x0002 ++#define PROXIMITY_NET 0x0004 ++#define PROXIMITY_OTHER 0x0008 ++#define PROXIMITY_UNSUPPORTED 0x0010 ++ + struct mapent; + + struct map_type_info { +@@ -26,6 +33,7 @@ struct map_type_info { + char *map; + }; + ++unsigned int get_proximity(struct sockaddr *); + const char *skipspace(const char *); + int check_colon(const char *); + int chunklen(const char *, int); +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index dd2a784..b77d890 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -18,8 +18,24 @@ + #include + #include + #include ++#include ++#include ++#include + #include "automount.h" + ++#define MAX_NETWORK_LEN 255 ++ ++#define MAX_IFC_BUF 2048 ++static int volatile ifc_buf_len = MAX_IFC_BUF; ++static int volatile ifc_last_len = 0; ++ ++#define MASK_A 0x7F000000 ++#define MASK_B 0xBFFF0000 ++#define MASK_C 0xDFFFFF00 ++ ++/* Get numeric value of the n bits starting at position p */ ++#define getbits(x, p, n) ((x >> (p + 1 - n)) & ~(~0 << n)) ++ + struct types { + char *type; + unsigned int len; +@@ -45,6 +61,189 @@ static struct types format_type[] = { + }; + static unsigned int format_type_count = sizeof(format_type)/sizeof(struct types); + ++static unsigned int ipv6_mask_cmp(uint32_t *host, uint32_t *iface, uint32_t *mask) ++{ ++ unsigned int ret = 1; ++ unsigned int i; ++ ++ for (i = 0; i < 4; i++) { ++ if ((host[i] & mask[i]) != (iface[i] & mask[i])) { ++ ret = 0; ++ break; ++ } ++ } ++ return ret; ++} ++ ++unsigned int get_proximity(struct sockaddr *host_addr) ++{ ++ struct ifaddrs *ifa = NULL; ++ struct ifaddrs *this; ++ struct sockaddr_in *addr, *msk_addr, *if_addr; ++ struct sockaddr_in6 *addr6, *msk6_addr, *if6_addr; ++ struct in_addr *hst_addr; ++ struct in6_addr *hst6_addr; ++ int addr_len; ++ char buf[MAX_ERR_BUF]; ++ uint32_t mask, ha, ia, *mask6, *ha6, *ia6; ++ int ret; ++ ++ addr = NULL; ++ addr6 = NULL; ++ hst_addr = NULL; ++ hst6_addr = NULL; ++ mask6 = NULL; ++ ha6 = NULL; ++ ia6 = NULL; ++ ha = 0; ++ ++ switch (host_addr->sa_family) { ++ case AF_INET: ++ addr = (struct sockaddr_in *) host_addr; ++ hst_addr = (struct in_addr *) &addr->sin_addr; ++ ha = ntohl((uint32_t) hst_addr->s_addr); ++ addr_len = sizeof(*hst_addr); ++ break; ++ ++ case AF_INET6: ++#ifndef WITH_LIBTIRPC ++ return PROXIMITY_UNSUPPORTED; ++#else ++ addr6 = (struct sockaddr_in6 *) host_addr; ++ hst6_addr = (struct in6_addr *) &addr6->sin6_addr; ++ ha6 = &hst6_addr->s6_addr32[0]; ++ addr_len = sizeof(*hst6_addr); ++ break; ++#endif ++ ++ default: ++ return PROXIMITY_ERROR; ++ } ++ ++ ret = getifaddrs(&ifa); ++ if (ret) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ logerr("getifaddrs: %s", estr); ++ return PROXIMITY_ERROR; ++ } ++ ++ this = ifa; ++ while (this) { ++ if (!(this->ifa_flags & IFF_UP) || ++ this->ifa_flags & IFF_POINTOPOINT || ++ this->ifa_addr == NULL) { ++ this = this->ifa_next; ++ continue; ++ } ++ ++ switch (this->ifa_addr->sa_family) { ++ case AF_INET: ++ if (host_addr->sa_family == AF_INET6) ++ break; ++ if_addr = (struct sockaddr_in *) this->ifa_addr; ++ ret = memcmp(&if_addr->sin_addr, hst_addr, addr_len); ++ if (!ret) { ++ freeifaddrs(ifa); ++ return PROXIMITY_LOCAL; ++ } ++ break; ++ ++ case AF_INET6: ++#ifdef WITH_LIBTIRPC ++ if (host_addr->sa_family == AF_INET) ++ break; ++ if6_addr = (struct sockaddr_in6 *) this->ifa_addr; ++ ret = memcmp(&if6_addr->sin6_addr, hst6_addr, addr_len); ++ if (!ret) { ++ freeifaddrs(ifa); ++ return PROXIMITY_LOCAL; ++ } ++#endif ++ default: ++ break; ++ } ++ this = this->ifa_next; ++ } ++ ++ this = ifa; ++ while (this) { ++ if (!(this->ifa_flags & IFF_UP) || ++ this->ifa_flags & IFF_POINTOPOINT || ++ this->ifa_addr == NULL) { ++ this = this->ifa_next; ++ continue; ++ } ++ ++ switch (this->ifa_addr->sa_family) { ++ case AF_INET: ++ if (host_addr->sa_family == AF_INET6) ++ break; ++ if_addr = (struct sockaddr_in *) this->ifa_addr; ++ ia = ntohl((uint32_t) if_addr->sin_addr.s_addr); ++ ++ /* Is the address within a localy attached subnet */ ++ ++ msk_addr = (struct sockaddr_in *) this->ifa_netmask; ++ mask = ntohl((uint32_t) msk_addr->sin_addr.s_addr); ++ ++ if ((ia & mask) == (ha & mask)) { ++ freeifaddrs(ifa); ++ return PROXIMITY_SUBNET; ++ } ++ ++ /* ++ * Is the address within a local ipv4 network. ++ * ++ * Bit position 31 == 0 => class A. ++ * Bit position 30 == 0 => class B. ++ * Bit position 29 == 0 => class C. ++ */ ++ ++ if (!getbits(ia, 31, 1)) ++ mask = MASK_A; ++ else if (!getbits(ia, 30, 1)) ++ mask = MASK_B; ++ else if (!getbits(ia, 29, 1)) ++ mask = MASK_C; ++ else ++ break; ++ ++ if ((ia & mask) == (ha & mask)) { ++ freeifaddrs(ifa); ++ return PROXIMITY_NET; ++ } ++ break; ++ ++ case AF_INET6: ++#ifdef WITH_LIBTIRPC ++ if (host_addr->sa_family == AF_INET) ++ break; ++ if6_addr = (struct sockaddr_in6 *) this->ifa_addr; ++ ia6 = &if6_addr->sin6_addr.s6_addr32[0]; ++ ++ /* Is the address within the network of the interface */ ++ ++ msk6_addr = (struct sockaddr_in6 *) this->ifa_netmask; ++ mask6 = &msk6_addr->sin6_addr.s6_addr32[0]; ++ ++ if (ipv6_mask_cmp(ha6, ia6, mask6)) { ++ freeifaddrs(ifa); ++ return PROXIMITY_SUBNET; ++ } ++ ++ /* How do we define "local network" in ipv6? */ ++#endif ++ default: ++ break; ++ } ++ this = this->ifa_next; ++ } ++ ++ freeifaddrs(ifa); ++ ++ return PROXIMITY_OTHER; ++} ++ + /* + * Skip whitespace in a string; if we hit a #, consider the rest of the + * entry a comment. +diff --git a/modules/replicated.c b/modules/replicated.c +index d43f778..0c1a8a7 100644 +--- a/modules/replicated.c ++++ b/modules/replicated.c +@@ -48,11 +48,8 @@ + #include + #include + #include +-#include +-#include + #include + #include +-#include + + #include "rpc_subs.h" + #include "replicated.h" +@@ -62,34 +59,9 @@ + #define MAX_ERR_BUF 512 + #endif + +-#define MAX_IFC_BUF 2048 +-static int volatile ifc_buf_len = MAX_IFC_BUF; +-static int volatile ifc_last_len = 0; +- +-#define MASK_A 0x7F000000 +-#define MASK_B 0xBFFF0000 +-#define MASK_C 0xDFFFFF00 +- +-/* Get numeric value of the n bits starting at position p */ +-#define getbits(x, p, n) ((x >> (p + 1 - n)) & ~(~0 << n)) +- + #define mymax(x, y) (x >= y ? x : y) + #define mmax(x, y, z) (mymax(x, y) == x ? mymax(x, z) : mymax(y, z)) + +-unsigned int ipv6_mask_cmp(uint32_t *host, uint32_t *iface, uint32_t *mask) +-{ +- unsigned int ret = 1; +- unsigned int i; +- +- for (i = 0; i < 4; i++) { +- if ((host[i] & mask[i]) != (iface[i] & mask[i])) { +- ret = 0; +- break; +- } +- } +- return ret; +-} +- + void seed_random(void) + { + int fd; +@@ -111,175 +83,6 @@ void seed_random(void) + return; + } + +-static unsigned int get_proximity(struct sockaddr *host_addr) +-{ +- struct ifaddrs *ifa = NULL; +- struct ifaddrs *this; +- struct sockaddr_in *addr, *msk_addr, *if_addr; +- struct sockaddr_in6 *addr6, *msk6_addr, *if6_addr; +- struct in_addr *hst_addr; +- struct in6_addr *hst6_addr; +- int addr_len; +- char buf[MAX_ERR_BUF]; +- uint32_t mask, ha, ia, *mask6, *ha6, *ia6; +- int ret; +- +- addr = NULL; +- addr6 = NULL; +- hst_addr = NULL; +- hst6_addr = NULL; +- mask6 = NULL; +- ha6 = NULL; +- ia6 = NULL; +- ha = 0; +- +- switch (host_addr->sa_family) { +- case AF_INET: +- addr = (struct sockaddr_in *) host_addr; +- hst_addr = (struct in_addr *) &addr->sin_addr; +- ha = ntohl((uint32_t) hst_addr->s_addr); +- addr_len = sizeof(*hst_addr); +- break; +- +- case AF_INET6: +-#ifndef WITH_LIBTIRPC +- return PROXIMITY_UNSUPPORTED; +-#else +- addr6 = (struct sockaddr_in6 *) host_addr; +- hst6_addr = (struct in6_addr *) &addr6->sin6_addr; +- ha6 = &hst6_addr->s6_addr32[0]; +- addr_len = sizeof(*hst6_addr); +- break; +-#endif +- +- default: +- return PROXIMITY_ERROR; +- } +- +- ret = getifaddrs(&ifa); +- if (ret) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- logerr("getifaddrs: %s", estr); +- return PROXIMITY_ERROR; +- } +- +- this = ifa; +- while (this) { +- if (!(this->ifa_flags & IFF_UP) || +- this->ifa_flags & IFF_POINTOPOINT || +- this->ifa_addr == NULL) { +- this = this->ifa_next; +- continue; +- } +- +- switch (this->ifa_addr->sa_family) { +- case AF_INET: +- if (host_addr->sa_family == AF_INET6) +- break; +- if_addr = (struct sockaddr_in *) this->ifa_addr; +- ret = memcmp(&if_addr->sin_addr, hst_addr, addr_len); +- if (!ret) { +- freeifaddrs(ifa); +- return PROXIMITY_LOCAL; +- } +- break; +- +- case AF_INET6: +-#ifdef WITH_LIBTIRPC +- if (host_addr->sa_family == AF_INET) +- break; +- if6_addr = (struct sockaddr_in6 *) this->ifa_addr; +- ret = memcmp(&if6_addr->sin6_addr, hst6_addr, addr_len); +- if (!ret) { +- freeifaddrs(ifa); +- return PROXIMITY_LOCAL; +- } +-#endif +- default: +- break; +- } +- this = this->ifa_next; +- } +- +- this = ifa; +- while (this) { +- if (!(this->ifa_flags & IFF_UP) || +- this->ifa_flags & IFF_POINTOPOINT || +- this->ifa_addr == NULL) { +- this = this->ifa_next; +- continue; +- } +- +- switch (this->ifa_addr->sa_family) { +- case AF_INET: +- if (host_addr->sa_family == AF_INET6) +- break; +- if_addr = (struct sockaddr_in *) this->ifa_addr; +- ia = ntohl((uint32_t) if_addr->sin_addr.s_addr); +- +- /* Is the address within a localy attached subnet */ +- +- msk_addr = (struct sockaddr_in *) this->ifa_netmask; +- mask = ntohl((uint32_t) msk_addr->sin_addr.s_addr); +- +- if ((ia & mask) == (ha & mask)) { +- freeifaddrs(ifa); +- return PROXIMITY_SUBNET; +- } +- +- /* +- * Is the address within a local ipv4 network. +- * +- * Bit position 31 == 0 => class A. +- * Bit position 30 == 0 => class B. +- * Bit position 29 == 0 => class C. +- */ +- +- if (!getbits(ia, 31, 1)) +- mask = MASK_A; +- else if (!getbits(ia, 30, 1)) +- mask = MASK_B; +- else if (!getbits(ia, 29, 1)) +- mask = MASK_C; +- else +- break; +- +- if ((ia & mask) == (ha & mask)) { +- freeifaddrs(ifa); +- return PROXIMITY_NET; +- } +- break; +- +- case AF_INET6: +-#ifdef WITH_LIBTIRPC +- if (host_addr->sa_family == AF_INET) +- break; +- if6_addr = (struct sockaddr_in6 *) this->ifa_addr; +- ia6 = &if6_addr->sin6_addr.s6_addr32[0]; +- +- /* Is the address within the network of the interface */ +- +- msk6_addr = (struct sockaddr_in6 *) this->ifa_netmask; +- mask6 = &msk6_addr->sin6_addr.s6_addr32[0]; +- +- if (ipv6_mask_cmp(ha6, ia6, mask6)) { +- freeifaddrs(ifa); +- return PROXIMITY_SUBNET; +- } +- +- /* How do we define "local network" in ipv6? */ +-#endif +- default: +- break; +- } +- this = this->ifa_next; +- } +- +- freeifaddrs(ifa); +- +- return PROXIMITY_OTHER; +-} +- + struct host *new_host(const char *name, + struct sockaddr *addr, size_t addr_len, + unsigned int proximity, unsigned int weight, diff --git a/SOURCES/autofs-5.0.9-amd-lookup-rework-config-handling.patch b/SOURCES/autofs-5.0.9-amd-lookup-rework-config-handling.patch new file mode 100644 index 0000000..dfed20a --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-rework-config-handling.patch @@ -0,0 +1,1266 @@ +autofs-5.0.9 - amd lookup rework config handling + +From: Ian Kent + +Re-work the autofs configuration sub-system to use sections. +Initially this means we have an anonomous section (for backward +compatibility) and an "autofs" section for the autofs global +configuration. +--- + daemon/automount.c | 1 + include/automount.h | 18 + + include/defaults.h | 27 +- + lib/cache.c | 19 - + lib/defaults.c | 836 +++++++++++++++++++++++++++++++++++++-------------- + 5 files changed, 644 insertions(+), 257 deletions(-) + +diff --git a/daemon/automount.c b/daemon/automount.c +index 0dd6477..fd5a19b 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -2339,6 +2339,7 @@ int main(int argc, char *argv[]) + unlink(pid_file); + pid_file = NULL; + } ++ defaults_conf_release(); + closelog(); + release_flag_file(); + macro_free_global_table(); +diff --git a/include/automount.h b/include/automount.h +index 1aabfa4..6da1926 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -136,6 +136,24 @@ struct autofs_point; + #define UMOUNT_RETRIES 8 + #define EXPIRE_RETRIES 3 + ++static u_int32_t inline hash(const char *key, unsigned int size) ++{ ++ u_int32_t hashval; ++ char *s = (char *) key; ++ ++ for (hashval = 0; *s != '\0';) { ++ hashval += (unsigned char) *s++; ++ hashval += (hashval << 10); ++ hashval ^= (hashval >> 6); ++ } ++ ++ hashval += (hashval << 3); ++ hashval ^= (hashval >> 11); ++ hashval += (hashval << 15); ++ ++ return hashval % size; ++} ++ + struct mapent_cache { + pthread_rwlock_t rwlock; + unsigned int size; +diff --git a/include/defaults.h b/include/defaults.h +index 871e14b..3bfcd49 100644 +--- a/include/defaults.h ++++ b/include/defaults.h +@@ -2,7 +2,9 @@ + * + * defaults.h - system initialization defaults. + * +- * Copyright 2006 Ian Kent ++ * Copyright 2013 Red Hat, Inc. ++ * Copyright 2006, 2013 Ian Kent ++ * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -22,15 +24,15 @@ + + #define DEFAULT_MASTER_MAP_NAME "auto.master" + +-#define DEFAULT_TIMEOUT 600 +-#define DEFAULT_NEGATIVE_TIMEOUT 60 +-#define DEFAULT_MOUNT_WAIT -1 +-#define DEFAULT_UMOUNT_WAIT 12 +-#define DEFAULT_BROWSE_MODE 1 +-#define DEFAULT_LOGGING 0 ++#define DEFAULT_TIMEOUT "600" ++#define DEFAULT_NEGATIVE_TIMEOUT "60" ++#define DEFAULT_MOUNT_WAIT "-1" ++#define DEFAULT_UMOUNT_WAIT "12" ++#define DEFAULT_BROWSE_MODE "1" ++#define DEFAULT_LOGGING "none" + +-#define DEFAULT_LDAP_TIMEOUT -1 +-#define DEFAULT_LDAP_NETWORK_TIMEOUT 8 ++#define DEFAULT_LDAP_TIMEOUT "-1" ++#define DEFAULT_LDAP_NETWORK_TIMEOUT "8" + + #define DEFAULT_MAP_OBJ_CLASS "nisMap" + #define DEFAULT_ENTRY_OBJ_CLASS "nisObject" +@@ -38,11 +40,11 @@ + #define DEFAULT_ENTRY_ATTR "cn" + #define DEFAULT_VALUE_ATTR "nisMapEntry" + +-#define DEFAULT_NFS_MOUNT_PROTOCOL 3 +-#define DEFAULT_APPEND_OPTIONS 1 ++#define DEFAULT_MOUNT_NFS_DEFAULT_PROTOCOL "3" ++#define DEFAULT_APPEND_OPTIONS "1" + #define DEFAULT_AUTH_CONF_FILE AUTOFS_MAP_DIR "/autofs_ldap_auth.conf" + +-#define DEFAULT_MAP_HASH_TABLE_SIZE 1024 ++#define DEFAULT_MAP_HASH_TABLE_SIZE "1024" + + #ifdef WITH_LDAP + struct ldap_schema; +@@ -56,6 +58,7 @@ struct ldap_schema *defaults_get_schema(void); + #endif + + unsigned int defaults_read_config(unsigned int); ++void defaults_conf_release(void); + const char *defaults_get_master_map(void); + int defaults_master_set(void); + unsigned int defaults_get_timeout(void); +diff --git a/lib/cache.c b/lib/cache.c +index f2efcd3..9af1709 100644 +--- a/lib/cache.c ++++ b/lib/cache.c +@@ -20,7 +20,6 @@ + #include + #include + #include +-#include + #include + + #include "automount.h" +@@ -362,24 +361,6 @@ struct mapent_cache *cache_init_null_cache(struct master *master) + return mc; + } + +-static u_int32_t hash(const char *key, unsigned int size) +-{ +- u_int32_t hashval; +- char *s = (char *) key; +- +- for (hashval = 0; *s != '\0';) { +- hashval += (unsigned char) *s++; +- hashval += (hashval << 10); +- hashval ^= (hashval >> 6); +- } +- +- hashval += (hashval << 3); +- hashval ^= (hashval >> 11); +- hashval += (hashval << 15); +- +- return hashval % size; +-} +- + static u_int32_t ino_hash(dev_t dev, ino_t ino, unsigned int size) + { + u_int32_t hashval; +diff --git a/lib/defaults.c b/lib/defaults.c +index 7c65387..29f3f00 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -2,7 +2,9 @@ + * + * defaults.h - system initialization defaults. + * +- * Copyright 2006 Ian Kent - All Rights Reserved ++ * Copyright 2013 Red Hat, Inc. ++ * Copyright 2006, 2013 Ian Kent ++ * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -16,6 +18,7 @@ + #include + #include + #include ++#include + + #include "config.h" + #include "list.h" +@@ -26,132 +29,450 @@ + #include "log.h" + #include "automount.h" + +-#define DEFAULTS_CONFIG_FILE AUTOFS_CONF_DIR "/autofs" ++#define AUTOFS_GLOBAL_SECTION "autofs" ++ ++#define DEFAULT_CONFIG_FILE AUTOFS_CONF_DIR "/autofs" + #define MAX_LINE_LEN 256 + +-#define ENV_NAME_MASTER_MAP "MASTER_MAP_NAME" ++#define NAME_MASTER_MAP "master_map_name" ++ ++#define NAME_TIMEOUT "timeout" ++#define NAME_NEGATIVE_TIMEOUT "negative_timeout" ++#define NAME_BROWSE_MODE "browse_mode" ++#define NAME_LOGGING "logging" ++ ++#define NAME_LDAP_URI "ldap_uri" ++#define NAME_LDAP_TIMEOUT "ldap_timeout" ++#define NAME_LDAP_NETWORK_TIMEOUT "ldap_network_timeout" ++ ++#define NAME_SEARCH_BASE "search_base" + +-#define ENV_NAME_TIMEOUT "TIMEOUT" +-#define ENV_NAME_NEGATIVE_TIMEOUT "NEGATIVE_TIMEOUT" +-#define ENV_NAME_BROWSE_MODE "BROWSE_MODE" +-#define ENV_NAME_LOGGING "LOGGING" ++#define NAME_MAP_OBJ_CLASS "map_object_class" ++#define NAME_ENTRY_OBJ_CLASS "entry_object_class" ++#define NAME_MAP_ATTR "map_attribute" ++#define NAME_ENTRY_ATTR "entry_attribute" ++#define NAME_VALUE_ATTR "value_attribute" + +-#define LDAP_URI "LDAP_URI" +-#define ENV_LDAP_TIMEOUT "LDAP_TIMEOUT" +-#define ENV_LDAP_NETWORK_TIMEOUT "LDAP_NETWORK_TIMEOUT" ++#define NAME_MOUNT_NFS_DEFAULT_PROTOCOL "mount_nfs_default_protocol" ++#define NAME_APPEND_OPTIONS "append_options" ++#define NAME_MOUNT_WAIT "mount_wait" ++#define NAME_UMOUNT_WAIT "umount_wait" ++#define NAME_AUTH_CONF_FILE "auth_conf_file" + +-#define SEARCH_BASE "SEARCH_BASE" ++#define NAME_MAP_HASH_TABLE_SIZE "map_hash_table_size" + +-#define ENV_NAME_MAP_OBJ_CLASS "MAP_OBJECT_CLASS" +-#define ENV_NAME_ENTRY_OBJ_CLASS "ENTRY_OBJECT_CLASS" +-#define ENV_NAME_MAP_ATTR "MAP_ATTRIBUTE" +-#define ENV_NAME_ENTRY_ATTR "ENTRY_ATTRIBUTE" +-#define ENV_NAME_VALUE_ATTR "VALUE_ATTRIBUTE" ++/* Status returns */ ++#define CFG_OK 0x0000 ++#define CFG_FAIL 0x0001 ++#define CFG_EXISTS 0x0002 ++#define CFG_NOTFOUND 0x0004 + +-#define ENV_MOUNT_NFS_DEFAULT_PROTOCOL "MOUNT_NFS_DEFAULT_PROTOCOL" +-#define ENV_APPEND_OPTIONS "APPEND_OPTIONS" +-#define ENV_MOUNT_WAIT "MOUNT_WAIT" +-#define ENV_UMOUNT_WAIT "UMOUNT_WAIT" +-#define ENV_AUTH_CONF_FILE "AUTH_CONF_FILE" ++/* Config entry flags */ ++#define CONF_ENV 0x00000001 + +-#define ENV_MAP_HASH_TABLE_SIZE "MAP_HASH_TABLE_SIZE" ++#define CFG_TABLE_SIZE 128 + + static const char *default_master_map_name = DEFAULT_MASTER_MAP_NAME; + static const char *default_auth_conf_file = DEFAULT_AUTH_CONF_FILE; ++static const char *autofs_gbl_sec = AUTOFS_GLOBAL_SECTION; ++ ++struct conf_option { ++ char *section; ++ char *name; ++ char *value; ++ unsigned long flags; ++ struct conf_option *next; ++}; ++ ++struct conf_cache { ++ struct conf_option **hash; ++ time_t modified; ++}; ++static pthread_mutex_t conf_mutex = PTHREAD_MUTEX_INITIALIZER; ++static struct conf_cache *config = NULL; ++ ++static int conf_load_autofs_defaults(void); ++static int conf_update(const char *, const char *, const char *, unsigned long); ++static void conf_delete(const char *, const char *); ++static struct conf_option *conf_lookup(const char *, const char *); ++ ++ ++static void message(unsigned int to_syslog, const char *msg, ...) ++{ ++ va_list ap; ++ ++ va_start(ap, msg); ++ if (to_syslog) ++ vsyslog(LOG_CRIT, msg, ap); ++ else { ++ vfprintf(stderr, msg, ap); ++ fputc('\n', stderr); ++ } ++ va_end(ap); ++ ++ return; ++} + +-static char *get_env_string(const char *name) ++static int conf_init(void) + { +- char *val, *res; ++ struct conf_cache *cc; ++ unsigned int size = CFG_TABLE_SIZE; ++ unsigned int i; ++ ++ cc = malloc(sizeof(struct conf_cache)); ++ if (!cc) ++ return CFG_FAIL; ++ cc->modified = 0; ++ ++ cc->hash = malloc(size * sizeof(struct conf_option *)); ++ if (!cc->hash) { ++ free(cc); ++ return CFG_FAIL; ++ } + +- val = getenv(name); +- if (!val) +- return NULL; ++ for (i = 0; i < size; i++) { ++ cc->hash[i] = NULL; ++ } + +- res = strdup(val); +- if (!res) +- return NULL; ++ config = cc; + +- return res; ++ return CFG_OK; + } + +-static long get_env_number(const char *name) ++static void __conf_release(void) + { +- char *val; +- long res = -1; +- +- val = getenv(name); +- if (!val) +- return -1; ++ struct conf_cache *cc = config; ++ unsigned int size = CFG_TABLE_SIZE; ++ struct conf_option *co, *next; ++ unsigned int i; ++ ++ for (i = 0; i < size; i++) { ++ co = cc->hash[i]; ++ if (co == NULL) ++ continue; ++ next = co->next; ++ free(co->section); ++ free(co->name); ++ if (co->value) ++ free(co->value); ++ free(co); ++ ++ while (next) { ++ co = next; ++ next = co->next; ++ free(co->section); ++ free(co->name); ++ if (co->value) ++ free(co->value); ++ free(co); ++ } ++ cc->hash[i] = NULL; ++ } + +- if (isdigit(*val)) +- res = atol(val); ++ free(cc->hash); ++ free(cc); ++ config = NULL; + +- if (res < 0) +- return -1; ++ return; ++} + +- return res; ++void defaults_conf_release(void) ++{ ++ pthread_mutex_lock(&conf_mutex); ++ __conf_release(); ++ pthread_mutex_unlock(&conf_mutex); ++ return; + } + +-static int get_env_yesno(const char *name) ++static int conf_load_autofs_defaults(void) + { +- const char *val; +- int res = -1; ++ struct conf_option *co; ++ const char *sec = autofs_gbl_sec; ++ int ret; + +- val = getenv(name); +- if (!val) +- return -1; ++ ret = conf_update(sec, NAME_MASTER_MAP, ++ DEFAULT_MASTER_MAP_NAME, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_TIMEOUT, ++ DEFAULT_TIMEOUT, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_NEGATIVE_TIMEOUT, ++ DEFAULT_NEGATIVE_TIMEOUT, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_BROWSE_MODE, ++ DEFAULT_BROWSE_MODE, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_LOGGING, ++ DEFAULT_LOGGING, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_LDAP_TIMEOUT, ++ DEFAULT_LDAP_TIMEOUT, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_LDAP_NETWORK_TIMEOUT, ++ DEFAULT_LDAP_NETWORK_TIMEOUT, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_MAP_OBJ_CLASS, ++ DEFAULT_MAP_OBJ_CLASS, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_ENTRY_OBJ_CLASS, ++ DEFAULT_ENTRY_OBJ_CLASS, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_MAP_ATTR, ++ DEFAULT_MAP_ATTR, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_ENTRY_ATTR, ++ DEFAULT_ENTRY_ATTR, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_VALUE_ATTR, ++ DEFAULT_VALUE_ATTR, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_APPEND_OPTIONS, ++ DEFAULT_APPEND_OPTIONS, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_MOUNT_WAIT, ++ DEFAULT_MOUNT_WAIT, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_UMOUNT_WAIT, ++ DEFAULT_UMOUNT_WAIT, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_AUTH_CONF_FILE, ++ DEFAULT_AUTH_CONF_FILE, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ ret = conf_update(sec, NAME_MOUNT_NFS_DEFAULT_PROTOCOL, ++ DEFAULT_MOUNT_NFS_DEFAULT_PROTOCOL, CONF_ENV); ++ if (ret == CFG_FAIL) ++ goto error; ++ ++ /* LDAP_URI nad SEARCH_BASE can occur multiple times */ ++ while ((co = conf_lookup(sec, NAME_LDAP_URI))) ++ conf_delete(co->section, co->name); ++ ++ while ((co = conf_lookup(sec, NAME_SEARCH_BASE))) ++ conf_delete(co->section, co->name); + +- if (isdigit(*val)) +- res = atoi(val); +- else if (!strcasecmp(val, "yes")) +- return 1; +- else if (!strcasecmp(val, "no")) +- return 0; ++ return 1; + +- return res; ++error: ++ return 0; + } + +-/* +- * We've changed the key names so we need to check for the +- * config key and it's old name for backward conpatibility. +-*/ +-static int check_set_config_value(const char *res, const char *name, const char *value, unsigned to_syslog) ++static int conf_add(const char *section, const char *key, const char *value, unsigned long flags) + { +- char *old_name; ++ struct conf_option *co; ++ char *sec, *name, *val, *tmp; ++ unsigned int size = CFG_TABLE_SIZE; ++ u_int32_t index; + int ret; + +- if (!strcasecmp(res, name)) { +- ret = setenv(name, value, 0); +- if (ret) { +- if (!to_syslog) +- fprintf(stderr, +- "can't set config value for %s, " +- "error %d\n", name, ret); +- else +- logmsg("can't set config value for %s, " +- "error %d", name, ret); ++ sec = name = val = NULL; ++ ++ co = conf_lookup(section, key); ++ if (co) { ++ ret = CFG_EXISTS; ++ goto error; ++ } ++ ++ ret = CFG_FAIL; ++ ++ /* Environment overrides file value */ ++ if (((flags & CFG_ENV) && (tmp = getenv(key))) || value) { ++ if (tmp) ++ val = strdup(tmp); ++ else ++ val = strdup(value); ++ if (!val) ++ goto error; ++ } ++ ++ name = strdup(key); ++ if (!key) ++ goto error; ++ ++ sec = strdup(section); ++ if (!sec) ++ goto error; ++ ++ co = malloc(sizeof(struct conf_option)); ++ if (!co) ++ goto error; ++ ++ co->section = sec; ++ co->name = name; ++ co->value = val; ++ co->flags = flags; ++ co->next = NULL; ++ ++ /* Don't change user set values in the environment */ ++ if (flags & CONF_ENV) ++ setenv(name, value, 0); ++ ++ index = hash(key, size); ++ if (!config->hash[index]) ++ config->hash[index] = co; ++ else { ++ struct conf_option *last = NULL, *next; ++ next = config->hash[index]; ++ while (next) { ++ last = next; ++ next = last->next; + } +- return 1; ++ last->next = co; + } + +- old_name = alloca(strlen(name) + 9); +- strcpy(old_name, "DEFAULT_"); +- strcat(old_name, name); ++ return CFG_OK; ++ ++error: ++ if (name) ++ free(name); ++ if (val) ++ free(val); ++ if (sec) ++ free(sec); ++ ++ return ret; ++} + +- if (!strcasecmp(res, old_name)) { +- ret = setenv(name, value, 0); +- if (ret) { +- if (!to_syslog) +- fprintf(stderr, +- "can't set config value for %s, " +- "error %d\n", name, ret); ++static void conf_delete(const char *section, const char *key) ++{ ++ struct conf_option *co, *last; ++ unsigned int size = CFG_TABLE_SIZE; ++ ++ last = NULL; ++ for (co = config->hash[hash(key, size)]; co != NULL; co = co->next) { ++ if (strcasecmp(section, co->section)) ++ continue; ++ if (!strcasecmp(key, co->name)) ++ break; ++ last = co; ++ } ++ ++ if (!co) ++ return; ++ ++ if (last) ++ last->next = co->next; ++ ++ free(co->section); ++ free(co->name); ++ if (co->value); ++ free(co->value); ++ free(co); ++} ++ ++static int conf_update(const char *section, ++ const char *key, const char *value, ++ unsigned long flags) ++{ ++ struct conf_option *co = NULL; ++ int ret; ++ ++ ret = CFG_FAIL; ++ co = conf_lookup(section, key); ++ if (!co) ++ ret = conf_add(section, key, value, flags); ++ else { ++ char *val = NULL, *tmp; ++ /* Environment overrides file value */ ++ if (((flags & CONF_ENV) && (tmp = getenv(key))) || value) { ++ if (tmp) ++ val = strdup(tmp); + else +- logmsg("can't set config value for %s, " +- "error %d\n", name, ret); ++ val = strdup(value); ++ if (!val) ++ goto error; + } +- return 1; ++ if (co->value) ++ free(co->value); ++ co->value = val; ++ if (flags) ++ co->flags = flags; ++ /* Don't change user set values in the environment */ ++ if (flags & CONF_ENV) ++ setenv(key, value, 0); + } +- return 0; ++ ++ return CFG_OK; ++ ++error: ++ return ret; ++} ++ ++static struct conf_option *conf_lookup(const char *section, const char *key) ++{ ++ struct conf_option *co; ++ unsigned int size = CFG_TABLE_SIZE; ++ ++ if (!key || !section) ++ return NULL; ++ ++ for (co = config->hash[hash(key, size)]; co != NULL; co = co->next) { ++ if (strcasecmp(section, co->section)) ++ continue; ++ if (!strcasecmp(key, co->name)) ++ break; ++ /* ++ * Strip "DEFAULT_" and look for config entry for ++ * backward compatibility with old style config names. ++ */ ++ if (strlen(key) <= 8) ++ continue; ++ if (!strncasecmp("DEFAULT_", key, 8) && ++ !strcasecmp(key + 8, co->name)) ++ break; ++ } ++ ++ return co; ++} ++ ++/* ++ * We've changed the key names so we need to check for the ++ * config key and it's old name for backward conpatibility. ++*/ ++static int check_set_config_value(const char *res, const char *value) ++{ ++ const char *sec = autofs_gbl_sec; ++ int ret; ++ ++ if (!strcasecmp(res, NAME_LDAP_URI)) ++ ret = conf_add(sec, res, value, 0); ++ else if (!strcasecmp(res, NAME_SEARCH_BASE)) ++ ret = conf_add(sec, res, value, 0); ++ else ++ ret = conf_update(sec, res, value, 0); ++ ++ return ret; + } + + static int parse_line(char *line, char **res, char **value) +@@ -200,6 +521,119 @@ static int parse_line(char *line, char **res, char **value) + return 1; + } + ++/* ++ * Read config env variables and check they have been set. ++ * ++ * This simple minded routine assumes the config file ++ * is valid bourne shell script without spaces around "=" ++ * and that it has valid values. ++ */ ++unsigned int defaults_read_config(unsigned int to_syslog) ++{ ++ FILE *f; ++ char buf[MAX_LINE_LEN]; ++ struct stat stb; ++ char *res; ++ int ret; ++ ++ f = open_fopen_r(DEFAULT_CONFIG_FILE); ++ if (!f) ++ return 0; ++ ++ pthread_mutex_lock(&conf_mutex); ++ if (config) { ++ if (fstat(fileno(f), &stb) != -1) { ++ /* Config hasn't been updated */ ++ if (stb.st_mtime <= config->modified) ++ goto out; ++ } ++ } else { ++ if (conf_init()) { ++ pthread_mutex_unlock(&conf_mutex); ++ message(to_syslog, "failed to init config"); ++ return 0; ++ } ++ } ++ ++ /* Set configuration to defaults */ ++ ret = conf_load_autofs_defaults(); ++ if (!ret) { ++ pthread_mutex_unlock(&conf_mutex); ++ message(to_syslog, "failed to reset autofs default config"); ++ return 0; ++ } ++ ++ while ((res = fgets(buf, MAX_LINE_LEN, f))) { ++ char *key, *value; ++ if (!parse_line(res, &key, &value)) ++ continue; ++ check_set_config_value(key, value); ++ } ++ ++ if (fstat(fileno(f), &stb) != -1) ++ config->modified = stb.st_mtime; ++ else ++ message(to_syslog, "failed to update config modified time"); ++ ++ if (!feof(f) || ferror(f)) { ++ pthread_mutex_unlock(&conf_mutex); ++ message(to_syslog, ++ "fgets returned error %d while reading %s", ++ ferror(f), DEFAULT_CONFIG_FILE); ++ fclose(f); ++ return 0; ++ } ++out: ++ pthread_mutex_unlock(&conf_mutex); ++ fclose(f); ++ return 1; ++} ++ ++static char *conf_get_string(const char *section, const char *name) ++{ ++ struct conf_option *co; ++ char *val = NULL; ++ ++ pthread_mutex_lock(&conf_mutex); ++ co = conf_lookup(section, name); ++ if (co && co->value) ++ val = strdup(co->value); ++ pthread_mutex_unlock(&conf_mutex); ++ return val; ++} ++ ++static long conf_get_number(const char *section, const char *name) ++{ ++ struct conf_option *co; ++ long val = -1; ++ ++ pthread_mutex_lock(&conf_mutex); ++ co = conf_lookup(section, name); ++ if (co && co->value) ++ val = atol(co->value); ++ pthread_mutex_unlock(&conf_mutex); ++ return val; ++} ++ ++static int conf_get_yesno(const char *section, const char *name) ++{ ++ struct conf_option *co; ++ int val = -1; ++ ++ pthread_mutex_lock(&conf_mutex); ++ co = conf_lookup(section, name); ++ if (co && co->value) { ++ if (isdigit(*co->value)) ++ val = atoi(co->value); ++ else if (!strcasecmp(co->value, "yes")) ++ val = 1; ++ else if (!strcasecmp(co->value, "no")) ++ val = 0; ++ } ++ pthread_mutex_unlock(&conf_mutex); ++ return val; ++} ++ + #ifdef WITH_LDAP + void defaults_free_uris(struct list_head *list) + { +@@ -229,7 +663,7 @@ static unsigned int add_uris(char *value, struct list_head *list) + char *str, *tok, *ptr = NULL; + size_t len = strlen(value) + 1; + +- str = alloca(len); ++ str = malloc(len); + if (!str) + return 0; + strcpy(str, value); +@@ -253,44 +687,48 @@ static unsigned int add_uris(char *value, struct list_head *list) + + tok = strtok_r(NULL, " ", &ptr); + } ++ free(str); + + return 1; + } + + struct list_head *defaults_get_uris(void) + { +- FILE *f; +- char buf[MAX_LINE_LEN]; +- char *res; ++ struct conf_option *co; + struct list_head *list; + +- f = open_fopen_r(DEFAULTS_CONFIG_FILE); +- if (!f) +- return NULL; +- + list = malloc(sizeof(struct list_head)); + if (!list) { +- fclose(f); + return NULL; + } + INIT_LIST_HEAD(list); + +- while ((res = fgets(buf, MAX_LINE_LEN, f))) { +- char *key, *value; ++ if (defaults_read_config(0)) { ++ free(list); ++ return NULL; ++ } + +- if (!parse_line(res, &key, &value)) +- continue; ++ pthread_mutex_lock(&conf_mutex); ++ co = conf_lookup(autofs_gbl_sec, NAME_LDAP_URI); ++ if (!co || !co->value) { ++ pthread_mutex_unlock(&conf_mutex); ++ free(list); ++ return NULL; ++ } + +- if (!strcasecmp(res, LDAP_URI)) +- add_uris(value, list); ++ while (co) { ++ if (!strcasecmp(co->name, NAME_LDAP_URI)) ++ if (co->value) ++ add_uris(co->value, list); ++ co = co->next; + } ++ pthread_mutex_unlock(&conf_mutex); + + if (list_empty(list)) { + free(list); + list = NULL; + } + +- fclose(f); + return list; + } + +@@ -390,45 +828,50 @@ void defaults_free_searchdns(struct ldap_searchdn *sdn) + + struct ldap_searchdn *defaults_get_searchdns(void) + { +- FILE *f; +- char buf[MAX_LINE_LEN]; +- char *res; ++ struct conf_option *co; + struct ldap_searchdn *sdn, *last; + +- f = open_fopen_r(DEFAULTS_CONFIG_FILE); +- if (!f) ++ if (defaults_read_config(0)) + return NULL; + ++ pthread_mutex_lock(&conf_mutex); ++ co = conf_lookup(autofs_gbl_sec, NAME_SEARCH_BASE); ++ if (!co || !co->value) { ++ pthread_mutex_unlock(&conf_mutex); ++ return NULL; ++ } ++ + sdn = last = NULL; + +- while ((res = fgets(buf, MAX_LINE_LEN, f))) { +- char *key, *value; ++ while (co) { ++ struct ldap_searchdn *new; + +- if (!parse_line(res, &key, &value)) ++ if (!co->value || strcasecmp(co->name, NAME_SEARCH_BASE) ) { ++ co = co->next; + continue; ++ } + +- if (!strcasecmp(key, SEARCH_BASE)) { +- struct ldap_searchdn *new = alloc_searchdn(value); ++ new = alloc_searchdn(co->value); ++ if (!new) { ++ pthread_mutex_unlock(&conf_mutex); ++ defaults_free_searchdns(sdn); ++ return NULL; ++ } + +- if (!new) { +- defaults_free_searchdns(sdn); +- fclose(f); +- return NULL; +- } ++ if (!last) ++ last = new; ++ else { ++ last->next = new; ++ last = new; ++ } + +- if (!last) +- last = new; +- else { +- last->next = new; +- last = new; +- } ++ if (!sdn) ++ sdn = new; + +- if (!sdn) +- sdn = new; +- } ++ co = co->next; + } ++ pthread_mutex_unlock(&conf_mutex); + +- fclose(f); + return sdn; + } + +@@ -436,25 +879,26 @@ struct ldap_schema *defaults_get_schema(void) + { + struct ldap_schema *schema; + char *mc, *ma, *ec, *ea, *va; ++ const char *sec = autofs_gbl_sec; + +- mc = get_env_string(ENV_NAME_MAP_OBJ_CLASS); ++ mc = conf_get_string(sec, NAME_MAP_OBJ_CLASS); + if (!mc) + return NULL; + +- ma = get_env_string(ENV_NAME_MAP_ATTR); ++ ma = conf_get_string(sec, NAME_MAP_ATTR); + if (!ma) { + free(mc); + return NULL; + } + +- ec = get_env_string(ENV_NAME_ENTRY_OBJ_CLASS); ++ ec = conf_get_string(sec, NAME_ENTRY_OBJ_CLASS); + if (!ec) { + free(mc); + free(ma); + return NULL; + } + +- ea = get_env_string(ENV_NAME_ENTRY_ATTR); ++ ea = conf_get_string(sec, NAME_ENTRY_ATTR); + if (!ea) { + free(mc); + free(ma); +@@ -462,7 +906,7 @@ struct ldap_schema *defaults_get_schema(void) + return NULL; + } + +- va = get_env_string(ENV_NAME_VALUE_ATTR); ++ va = conf_get_string(sec, NAME_VALUE_ATTR); + if (!va) { + free(mc); + free(ma); +@@ -491,72 +935,9 @@ struct ldap_schema *defaults_get_schema(void) + } + #endif + +-/* +- * Read config env variables and check they have been set. +- * +- * This simple minded routine assumes the config file +- * is valid bourne shell script without spaces around "=" +- * and that it has valid values. +- */ +-unsigned int defaults_read_config(unsigned int to_syslog) +-{ +- FILE *f; +- char buf[MAX_LINE_LEN]; +- char *res; +- +- f = open_fopen_r(DEFAULTS_CONFIG_FILE); +- if (!f) +- return 0; +- +- while ((res = fgets(buf, MAX_LINE_LEN, f))) { +- char *key, *value; +- +- if (!parse_line(res, &key, &value)) +- continue; +- +- if (check_set_config_value(key, ENV_NAME_MASTER_MAP, value, to_syslog) || +- check_set_config_value(key, ENV_NAME_TIMEOUT, value, to_syslog) || +- check_set_config_value(key, ENV_NAME_NEGATIVE_TIMEOUT, value, to_syslog) || +- check_set_config_value(key, ENV_NAME_BROWSE_MODE, value, to_syslog) || +- check_set_config_value(key, ENV_NAME_LOGGING, value, to_syslog) || +- check_set_config_value(key, ENV_LDAP_TIMEOUT, value, to_syslog) || +- check_set_config_value(key, ENV_LDAP_NETWORK_TIMEOUT, value, to_syslog) || +- check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value, to_syslog) || +- check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value, to_syslog) || +- check_set_config_value(key, ENV_NAME_MAP_ATTR, value, to_syslog) || +- check_set_config_value(key, ENV_NAME_ENTRY_ATTR, value, to_syslog) || +- check_set_config_value(key, ENV_NAME_VALUE_ATTR, value, to_syslog) || +- check_set_config_value(key, ENV_APPEND_OPTIONS, value, to_syslog) || +- check_set_config_value(key, ENV_MOUNT_WAIT, value, to_syslog) || +- check_set_config_value(key, ENV_UMOUNT_WAIT, value, to_syslog) || +- check_set_config_value(key, ENV_AUTH_CONF_FILE, value, to_syslog) || +- check_set_config_value(key, ENV_MAP_HASH_TABLE_SIZE, value, to_syslog) || +- check_set_config_value(key, ENV_MOUNT_NFS_DEFAULT_PROTOCOL, value, to_syslog)) +- ; +- } +- +- if (!feof(f) || ferror(f)) { +- if (!to_syslog) { +- fprintf(stderr, +- "fgets returned error %d while reading %s\n", +- ferror(f), DEFAULTS_CONFIG_FILE); +- } else { +- logmsg("fgets returned error %d while reading %s", +- ferror(f), DEFAULTS_CONFIG_FILE); +- } +- fclose(f); +- return 0; +- } +- +- fclose(f); +- return 1; +-} +- + const char *defaults_get_master_map(void) + { +- char *master; +- +- master = get_env_string(ENV_NAME_MASTER_MAP); ++ char *master = conf_get_string(autofs_gbl_sec, NAME_MASTER_MAP); + if (!master) + return strdup(default_master_map_name); + +@@ -565,20 +946,23 @@ const char *defaults_get_master_map(void) + + int defaults_master_set(void) + { +- char *val = getenv(ENV_NAME_MASTER_MAP); +- if (!val) +- return 0; ++ struct conf_option *co; + +- return 1; ++ pthread_mutex_lock(&conf_mutex); ++ co = conf_lookup(autofs_gbl_sec, NAME_MASTER_MAP); ++ pthread_mutex_unlock(&conf_mutex); ++ if (co) ++ return 1; ++ return 0; + } + + unsigned int defaults_get_timeout(void) + { + long timeout; + +- timeout = get_env_number(ENV_NAME_TIMEOUT); ++ timeout = conf_get_number(autofs_gbl_sec, NAME_TIMEOUT); + if (timeout < 0) +- timeout = DEFAULT_TIMEOUT; ++ timeout = atol(DEFAULT_TIMEOUT); + + return (unsigned int) timeout; + } +@@ -587,9 +971,9 @@ unsigned int defaults_get_negative_timeout(void) + { + long n_timeout; + +- n_timeout = get_env_number(ENV_NAME_NEGATIVE_TIMEOUT); ++ n_timeout = conf_get_number(autofs_gbl_sec, NAME_NEGATIVE_TIMEOUT); + if (n_timeout <= 0) +- n_timeout = DEFAULT_NEGATIVE_TIMEOUT; ++ n_timeout = atol(DEFAULT_NEGATIVE_TIMEOUT); + + return (unsigned int) n_timeout; + } +@@ -598,9 +982,9 @@ unsigned int defaults_get_browse_mode(void) + { + int res; + +- res = get_env_yesno(ENV_NAME_BROWSE_MODE); ++ res = conf_get_yesno(autofs_gbl_sec, NAME_BROWSE_MODE); + if (res < 0) +- res = DEFAULT_BROWSE_MODE; ++ res = atoi(DEFAULT_BROWSE_MODE); + + return res; + } +@@ -608,14 +992,14 @@ unsigned int defaults_get_browse_mode(void) + unsigned int defaults_get_logging(void) + { + char *res; +- unsigned int logging = DEFAULT_LOGGING; ++ unsigned int logging = LOGOPT_NONE; + +- res = get_env_string(ENV_NAME_LOGGING); ++ res = conf_get_string(autofs_gbl_sec, NAME_LOGGING); + if (!res) + return logging; + + if (!strcasecmp(res, "none")) +- logging = DEFAULT_LOGGING; ++ logging = LOGOPT_NONE; + else { + if (!strcasecmp(res, "verbose")) + logging |= LOGOPT_VERBOSE; +@@ -633,9 +1017,9 @@ unsigned int defaults_get_ldap_timeout(void) + { + int res; + +- res = get_env_number(ENV_LDAP_TIMEOUT); ++ res = conf_get_number(autofs_gbl_sec, NAME_LDAP_TIMEOUT); + if (res < 0) +- res = DEFAULT_LDAP_TIMEOUT; ++ res = atoi(DEFAULT_LDAP_TIMEOUT); + + return res; + } +@@ -644,20 +1028,20 @@ unsigned int defaults_get_ldap_network_timeout(void) + { + int res; + +- res = get_env_number(ENV_LDAP_NETWORK_TIMEOUT); ++ res = conf_get_number(autofs_gbl_sec, NAME_LDAP_NETWORK_TIMEOUT); + if (res < 0) +- res = DEFAULT_LDAP_NETWORK_TIMEOUT; ++ res = atoi(DEFAULT_LDAP_NETWORK_TIMEOUT); + + return res; + } + + unsigned int defaults_get_mount_nfs_default_proto(void) + { +- long proto; ++ int proto; + +- proto = get_env_number(ENV_MOUNT_NFS_DEFAULT_PROTOCOL); ++ proto = conf_get_number(autofs_gbl_sec, NAME_MOUNT_NFS_DEFAULT_PROTOCOL); + if (proto < 2 || proto > 4) +- proto = DEFAULT_NFS_MOUNT_PROTOCOL; ++ proto = atoi(DEFAULT_MOUNT_NFS_DEFAULT_PROTOCOL); + + return (unsigned int) proto; + } +@@ -666,9 +1050,9 @@ unsigned int defaults_get_append_options(void) + { + int res; + +- res = get_env_yesno(ENV_APPEND_OPTIONS); ++ res = conf_get_yesno(autofs_gbl_sec, NAME_APPEND_OPTIONS); + if (res < 0) +- res = DEFAULT_APPEND_OPTIONS; ++ res = atoi(DEFAULT_APPEND_OPTIONS); + + return res; + } +@@ -677,9 +1061,9 @@ unsigned int defaults_get_mount_wait(void) + { + long wait; + +- wait = get_env_number(ENV_MOUNT_WAIT); ++ wait = conf_get_number(autofs_gbl_sec, NAME_MOUNT_WAIT); + if (wait < 0) +- wait = DEFAULT_MOUNT_WAIT; ++ wait = atoi(DEFAULT_MOUNT_WAIT); + + return (unsigned int) wait; + } +@@ -688,9 +1072,9 @@ unsigned int defaults_get_umount_wait(void) + { + long wait; + +- wait = get_env_number(ENV_UMOUNT_WAIT); ++ wait = conf_get_number(autofs_gbl_sec, NAME_UMOUNT_WAIT); + if (wait < 0) +- wait = DEFAULT_UMOUNT_WAIT; ++ wait = atoi(DEFAULT_UMOUNT_WAIT); + + return (unsigned int) wait; + } +@@ -699,7 +1083,7 @@ const char *defaults_get_auth_conf_file(void) + { + char *cf; + +- cf = get_env_string(ENV_AUTH_CONF_FILE); ++ cf = conf_get_string(autofs_gbl_sec, NAME_AUTH_CONF_FILE); + if (!cf) + return strdup(default_auth_conf_file); + +@@ -710,9 +1094,9 @@ unsigned int defaults_get_map_hash_table_size(void) + { + long size; + +- size = get_env_number(ENV_MAP_HASH_TABLE_SIZE); ++ size = conf_get_number(autofs_gbl_sec, NAME_MAP_HASH_TABLE_SIZE); + if (size < 0) +- size = DEFAULT_MAP_HASH_TABLE_SIZE; ++ size = atoi(DEFAULT_MAP_HASH_TABLE_SIZE); + + return (unsigned int) size; + } diff --git a/SOURCES/autofs-5.0.9-amd-lookup-skip-sss-source-for-amd-lookups.patch b/SOURCES/autofs-5.0.9-amd-lookup-skip-sss-source-for-amd-lookups.patch new file mode 100644 index 0000000..041d465 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-skip-sss-source-for-amd-lookups.patch @@ -0,0 +1,41 @@ +autofs-5.0.9 - amd-lookup skip sss source for amd lookups + +From: Ian Kent + +Looks like we won't be able to provide sss as a map source for +amd maps. There's no way to tell sss to use a different schema +for different map formats. +--- + daemon/lookup.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -636,6 +636,13 @@ int lookup_nss_read_map(struct autofs_po + list_for_each(p, head) { + this = list_entry(p, struct nss_source, list); + ++ if (map->flags & MAP_FLAG_FORMAT_AMD && ++ !strcmp(this->source, "sss")) { ++ warn(ap->logopt, ++ "source sss is not available for amd maps."); ++ continue; ++ } ++ + debug(ap->logopt, + "reading map %s %s", this->source, map->argv[0]); + +@@ -1164,6 +1171,13 @@ int lookup_nss_mount(struct autofs_point + list_for_each(p, head) { + this = list_entry(p, struct nss_source, list); + ++ if (map->flags & MAP_FLAG_FORMAT_AMD && ++ !strcmp(this->source, "sss")) { ++ warn(ap->logopt, ++ "source sss is not available for amd maps."); ++ continue; ++ } ++ + result = lookup_map_name(this, ap, map, name, name_len); + + if (result == NSS_STATUS_UNKNOWN) diff --git a/SOURCES/autofs-5.0.9-amd-lookup-split-config-into-init-and-config-settings.patch b/SOURCES/autofs-5.0.9-amd-lookup-split-config-into-init-and-config-settings.patch new file mode 100644 index 0000000..bb5293f --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-split-config-into-init-and-config-settings.patch @@ -0,0 +1,809 @@ +autofs-5.0.9 - amd lookup split config into init and config settings + +From: Ian Kent + +Split the configuration into program and init time configuration files. +The bulk of the configuration is now in the daemon configuration file +in /etc/autofs.conf by default. + +The daemon configuration names are now lower case but in reality are +(and have always been) case insensitive. + +Also, read the old configuration from the old configuration location +after reading the new configuration to ensure that people updating +don't get a surprize if they don't update the existing setup they +have. Note that this means that if the old configuration isn't updated +changes made in the new configuration will be overridden by the old. +--- + autofs.spec | 2 + lib/defaults.c | 22 ++++++ + man/auto.master.5.in | 39 ++++++----- + redhat/Makefile | 6 - + redhat/autofs.conf.default.in | 131 ++++++++++++++++++++++++++++++++++++++ + redhat/autofs.sysconfig | 14 ++++ + redhat/autofs.sysconfig.in | 138 ----------------------------------------- + samples/Makefile | 44 ++++++++++--- + samples/autofs.conf.default.in | 109 +++++++++++++++----------------- + samples/autofs.init.conf | 14 ++++ + 10 files changed, 293 insertions(+), 226 deletions(-) + create mode 100644 redhat/autofs.conf.default.in + create mode 100644 redhat/autofs.sysconfig + delete mode 100644 redhat/autofs.sysconfig.in + create mode 100644 samples/autofs.init.conf + +--- autofs-5.0.7.orig/autofs.spec ++++ autofs-5.0.7/autofs.spec +@@ -117,6 +117,7 @@ install -m 644 redhat/autofs.service $RP + install -m 755 redhat/autofs.init $RPM_BUILD_ROOT/etc/rc.d/init.d/autofs + %define init_file_name /etc/rc.d/init.d/autofs + %endif ++install -m 644 redhat/autofs.conf $RPM_BUILD_ROOT/etc/autofs.conf + install -m 644 redhat/autofs.sysconfig $RPM_BUILD_ROOT/etc/sysconfig/autofs + + %clean +@@ -176,6 +177,7 @@ fi + %doc CREDITS CHANGELOG INSTALL COPY* README* samples/ldap* samples/autofs.schema samples/autofs_ldap_auth.conf + %config %{init_file_name} + %config(noreplace) /etc/auto.master ++%config(noreplace) /etc/autofs.conf + %config(noreplace,missingok) /etc/auto.misc + %config(noreplace,missingok) /etc/auto.net + %config(noreplace,missingok) /etc/auto.smb +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -33,7 +33,14 @@ + #define AUTOFS_GLOBAL_SECTION "autofs" + #define AMD_GLOBAL_SECTION "amd" + +-#define DEFAULT_CONFIG_FILE AUTOFS_CONF_DIR "/autofs" ++/* ++ * The configuration location has changed. ++ * The name of the configuration is now autofs.conf and it is ++ * located in the same directory as the maps. AUTOFS_CONF_DIR ++ * remains pointed at the init system configuration. ++ */ ++#define DEFAULT_CONFIG_FILE AUTOFS_MAP_DIR "/autofs.conf" ++#define OLD_CONFIG_FILE AUTOFS_CONF_DIR "/autofs" + #define MAX_LINE_LEN 256 + #define MAX_SECTION_NAME MAX_LINE_LEN + +@@ -965,6 +972,19 @@ unsigned int defaults_read_config(unsign + + fclose(f); + ++ /* ++ * Try to read the old config file and override the installed ++ * defaults in case user has a stale config following updating ++ * to the new config file location. ++ */ ++ ++ f = open_fopen_r(OLD_CONFIG_FILE); ++ if (!f) ++ goto out; ++ ++ read_config(to_syslog, f, OLD_CONFIG_FILE); ++ ++ fclose(f); + out: + pthread_mutex_unlock(&conf_mutex); + return 1; +--- autofs-5.0.7.orig/man/auto.master.5.in ++++ autofs-5.0.7/man/auto.master.5.in +@@ -214,44 +214,44 @@ configuration file + .hy + They are: + .TP +-.B TIMEOUT ++.B timeout + Sets the default mount timeout in seconds. The internal program + default is 10 minutes, but the default installed configuration + overrides this and sets the timeout to 5 minutes to be consistent + with earlier autofs releases. + .TP +-.B NEGATIVE_TIMEOUT ++.B negative_timeout + Set the default timeout for caching failed key lookups (program default + 60). If the equivalent command line option is given it will override this + setting. + .TP +-.B MOUNT_WAIT ++.B mount_wait + Set the default time to wait for a response from a spawned mount(8) + before sending it a SIGTERM. Note that we still need to wait for the + RPC layer to timeout before the sub-process exits so this isn't ideal + but it is the best we can do. The default is to wait until mount(8) + returns without intervention. + .TP +-.B UMOUNT_WAIT ++.B umount_wait + Set the default time to wait for a response from a spawned umount(8) + before sending it a SIGTERM. Note that we still need to wait for the + RPC layer to timeout before the sub-process exits so this isn't ideal + but it is the best we can do. + .TP +-.B BROWSE_MODE ++.B browse_mode + Maps are browsable by default (program default "yes"). + .TP +-.B MOUNT_NFS_DEFAULT_PROTOCOL ++.B mount_nfs_default_protocol + Specify the default protocol used by mount.nfs(8) (program default 3). Since + we can't identify this default automatically we need to set it in the autofs + configuration. + .TP +-.B APPEND_OPTIONS ++.B append_options + Determine whether global options, given on the command line or per mount + in the master map, are appended to map entry options or if the map entry + options replace the global options (program default "yes", append options). + .TP +-.B LOGGING ++.B logging + set default log level "none", "verbose" or "debug" (program default "none"). + .SH BUILTIN MAP -hosts + If "-hosts" is given as the map then accessing a key under the mount point +@@ -317,15 +317,15 @@ values must be set, any partial schema s + .P + The configuration settings available are: + .TP +-.B LDAP_TIMEOUT ++.B ldap_timeout + Set the network response timeout (default 8). + Set timeout value for the synchronous API calls. The default is the LDAP + library default of an infinite timeout. + .TP +-.B LDAP_NETWORK_TIMEOUT ++.B ldap_network_timeout + Set the network response timeout (default 8). + .TP +-.B LDAP_URI ++.B ldap_uri + A space seperated list of server uris of the form ://[/] + where can be ldap or ldaps. The option can be given multiple times. + Map entries that include a server name override this option and it is then +@@ -341,34 +341,34 @@ SRV RR lookup. The server list returned + according to the minimum ttl found in the SRV RR records or after one hour, + whichever is less. + .TP +-.B SEARCH_BASE ++.B search_base + The base dn to use when searching for amap base dn. This entry may be + given multiple times and each will be checked for a map base dn in + the order they occur in the configuration. The search base list is read + at startup and whenever the daemon recieves a HUP signal. + .TP +-.B MAP_OBJECT_CLASS ++.B map_object_class + The map object class. In the \fBnisMap\fP schema this corresponds to the class + \fBnisMap\fP and in the \fBautomountMap\fP schema it corresponds to the class + \fBautomountMap\fP. + .TP +-.B ENTRY_OBJECT_CLASS ++.B entry_object_class + The map entry object class. In the \fBnisMap\fP schema this corresponds + to the class \fBnisObject\fP and in the \fBautomountMap\fP schema it + corresponds to the class \fBautomount\fP. + .TP +-.B MAP_ATTRIBUTE ++.B map_attribute + The attribute used to identify the name of the map to which this + entry belongs. In the \fBnisMap\fP schema this corresponds to the attribute + \fBnisMapName\fP and in the \fBautomountMap\fP schema it corresponds to the + attribute \fBou\fP or \fBautomountMapName\fP. + .TP +-.B ENTRY_ATTRIBUTE ++.B entry_attribute + The attribute used to identify a map key. In the \fBnisMap\fP schema this + corresponds to the attribute \fBcn\fP and in the \fBautomountMap\fP schema + it corresponds to the attribute \fBautomountKey\fP. + .TP +-.B VALUE_ATTRIBUTE ++.B value_attribute + The attribute used to identify the value of the map entry. In the \fBnisMap\fP + schema this corresponds to the attribute \fBnisMapEntry\fP and in the \fBautomountMap\fP + schema it corresponds to the attribute \fBautomountInformation\fP. +@@ -386,6 +386,11 @@ settings. The default location of this + .nh + .BR @@autofsmapdir@@/autofs_ldap_auth.conf . + .hy ++.TP ++.B auth_conf_file ++This configuration option may be used to specify an alternate location ++for the ldap authentication file ++.P + If this file exists it will be used to establish whether TLS or authentication + should be used. + .P +--- autofs-5.0.7.orig/redhat/Makefile ++++ autofs-5.0.7/redhat/Makefile +@@ -2,7 +2,7 @@ + -include ../Makefile.conf + include ../Makefile.rules + +-all: autofs.init autofs.sysconfig autofs.service ++all: autofs.init autofs.conf autofs.service + + autofs.init: autofs.init.in + sed -e "s|@@sbindir@@|$(sbindir)|g" \ +@@ -11,9 +11,9 @@ autofs.init: autofs.init.in + -e "s|@@autofspiddir@@|$(autofspiddir)|g" \ + -e "s|@@initdir@@|$(initdir)|g" < autofs.init.in > autofs.init + +-autofs.sysconfig: autofs.sysconfig.in ++autofs.conf: autofs.conf.default.in + sed -e "s|@@autofsmapdir@@|$(autofsmapdir)|g" \ +- < autofs.sysconfig.in > autofs.sysconfig ++ < autofs.conf.default.in > autofs.conf + + autofs.service: ../samples/autofs.service.in + sed -e "s|@@sbindir@@|$(sbindir)|g" \ +--- /dev/null ++++ autofs-5.0.7/redhat/autofs.conf.default.in +@@ -0,0 +1,131 @@ ++# ++# Define default options for autofs. ++# ++[ autofs ] ++# ++# master_map_name - default map name for the master map. ++# ++#master_map_name = auto.master ++# ++# timeout - set the default mount timeout in secons. The internal ++# program default is 10 minutes, but the default installed ++# configuration overrides this and sets the timeout to 5 ++# minutes to be consistent with earlier autofs releases. ++# ++timeout = 300 ++# ++# negative_timeout - set the default negative timeout for ++# failed mount attempts (default 60). ++# ++#negative_timeout = 60 ++# ++# mount_wait - time to wait for a response from mount(8). ++# Setting this timeout can cause problems when ++# mount would otherwise wait for a server that ++# is temporarily unavailable, such as when it's ++# restarting. The default setting (-1) of waiting ++# for mount(8) usually results in a wait of around ++# 3 minutes. ++# ++#mount_wait = -1 ++# ++# umount_wait - time to wait for a response from umount(8). ++# ++#umount_wait = 12 ++# ++# browse_mode - maps are browsable by default. ++# ++browse_mode = no ++# ++# mount_nfs_default_protocol - specify the default protocol used by ++# mount.nfs(8). Since we can't identify ++# the default automatically we need to ++# set it in our configuration. ++# ++#mount_nfs_default_protocol = 3 ++mount_nfs_default_protocol = 4 ++# ++# append_options - append to global options instead of replace. ++# ++#append_options = yes ++# ++# logging - set default log level "none", "verbose" or "debug" ++# ++#logging = none ++# ++# Define base dn for map dn lookup. ++# ++# Define server URIs ++# ++# ldap_uri - space seperated list of server uris of the form ++# ://[/] where can be ldap ++# or ldaps. The option can be given multiple times. ++# Map entries that include a server name override ++# this option. ++# ++# This configuration option can also be used to ++# request autofs lookup SRV RRs for a domain of ++# the form :///[]. Note that a ++# trailing "/" is not allowed when using this form. ++# If the domain dn is not specified the dns domain ++# name (if any) is used to construct the domain dn ++# for the SRV RR lookup. The server list returned ++# from an SRV RR lookup is refreshed according to ++# the minimum ttl found in the SRV RR records or ++# after one hour, whichever is less. ++# ++#ldap_uri = "" ++# ++# ldap_timeout - timeout value for the synchronous API calls ++# (default is LDAP library default). ++# ++#ldap_timeout = -1 ++# ++# ldap_network_timeout - set the network response timeout (default 8). ++# ++#ldap_network_timeout = 8 ++# ++# search_base - base dn to use for searching for map search dn. ++# Multiple entries can be given and they are checked ++# in the order they occur here. ++# ++#search_base = "" ++# ++# Define the LDAP schema to used for lookups ++# ++# If no schema is set autofs will check each of the schemas ++# below in the order given to try and locate an appropriate ++# basdn for lookups. If you want to minimize the number of ++# queries to the server set the values here. ++# ++#map_object_class = nisMap ++#entry_object_class = nisObject ++#map_attribute = nisMapName ++#entry_attribute = cn ++#value_attribute= nisMapEntry ++# ++# Other common LDAP nameing ++# ++#map_object_class = automountMap ++#entry_object_class = automount ++#map_attribute = ou ++#entry_attribute = cn ++#value_attribute= automountInformation ++# ++#map_object_class = automountMap ++#entry_object_class = automount ++#map_attribute = automountMapName ++#entry_attribute = automountKey ++#value_attribute= automountInformation ++# ++# auth_conf_file - set the default location for the SASL ++# authentication configuration file. ++# ++#auth_conf_file = @@autofsmapdir@@/autofs_ldap_auth.conf ++# ++# map_hash_table_size - set the map cache hash table size. ++# Should be a power of 2 with a ratio roughly ++# between 1:10 and 1:20 for each map. ++# ++#map_hash_table_size = 1024 ++# +--- /dev/null ++++ autofs-5.0.7/redhat/autofs.sysconfig +@@ -0,0 +1,14 @@ ++# ++# Init syatem options ++# ++# If the kernel supports using the autofs miscellanous device ++# and you wish to use it you must set this configuration option ++# to "yes" otherwise it will not be used. ++# ++USE_MISC_DEVICE="yes" ++# ++# Use OPTIONS to add automount(8) command line options that ++# will be used when the daemon is started. ++# ++#OPTIONS="" ++# +--- autofs-5.0.7.orig/redhat/autofs.sysconfig.in ++++ /dev/null +@@ -1,138 +0,0 @@ +-# +-# Define default options for autofs. +-# +-# MASTER_MAP_NAME - default map name for the master map. +-# +-#MASTER_MAP_NAME="auto.master" +-# +-# TIMEOUT - set the default mount timeout in secons. The internal +-# program default is 10 minutes, but the default installed +-# configuration overrides this and sets the timeout to 5 +-# minutes to be consistent with earlier autofs releases. +-# +-TIMEOUT=300 +-# +-# NEGATIVE_TIMEOUT - set the default negative timeout for +-# failed mount attempts (default 60). +-# +-#NEGATIVE_TIMEOUT=60 +-# +-# MOUNT_WAIT - time to wait for a response from mount(8). +-# Setting this timeout can cause problems when +-# mount would otherwise wait for a server that +-# is temporarily unavailable, such as when it's +-# restarting. The default setting (-1) of waiting +-# for mount(8) usually results in a wait of around +-# 3 minutes. +-# +-#MOUNT_WAIT=-1 +-# +-# UMOUNT_WAIT - time to wait for a response from umount(8). +-# +-#UMOUNT_WAIT=12 +-# +-# BROWSE_MODE - maps are browsable by default. +-# +-BROWSE_MODE="no" +-# +-# MOUNT_NFS_DEFAULT_PROTOCOL - specify the default protocol used by +-# mount.nfs(8). Since we can't identify +-# the default automatically we need to +-# set it in our configuration. +-# +-#MOUNT_NFS_DEFAULT_PROTOCOL=3 +-MOUNT_NFS_DEFAULT_PROTOCOL=4 +-# +-# APPEND_OPTIONS - append to global options instead of replace. +-# +-#APPEND_OPTIONS="yes" +-# +-# LOGGING - set default log level "none", "verbose" or "debug" +-# +-#LOGGING="none" +-# +-# Define base dn for map dn lookup. +-# +-# Define server URIs +-# +-# LDAP_URI - space seperated list of server uris of the form +-# ://[/] where can be ldap +-# or ldaps. The option can be given multiple times. +-# Map entries that include a server name override +-# this option. +-# +-# This configuration option can also be used to +-# request autofs lookup SRV RRs for a domain of +-# the form :///[]. Note that a +-# trailing "/" is not allowed when using this form. +-# If the domain dn is not specified the dns domain +-# name (if any) is used to construct the domain dn +-# for the SRV RR lookup. The server list returned +-# from an SRV RR lookup is refreshed according to +-# the minimum ttl found in the SRV RR records or +-# after one hour, whichever is less. +-# +-#LDAP_URI="" +-# +-# LDAP__TIMEOUT - timeout value for the synchronous API calls +-# (default is LDAP library default). +-# +-#LDAP_TIMEOUT=-1 +-# +-# LDAP_NETWORK_TIMEOUT - set the network response timeout (default 8). +-# +-#LDAP_NETWORK_TIMEOUT=8 +-# +-# SEARCH_BASE - base dn to use for searching for map search dn. +-# Multiple entries can be given and they are checked +-# in the order they occur here. +-# +-#SEARCH_BASE="" +-# +-# Define the LDAP schema to used for lookups +-# +-# If no schema is set autofs will check each of the schemas +-# below in the order given to try and locate an appropriate +-# basdn for lookups. If you want to minimize the number of +-# queries to the server set the values here. +-# +-#MAP_OBJECT_CLASS="nisMap" +-#ENTRY_OBJECT_CLASS="nisObject" +-#MAP_ATTRIBUTE="nisMapName" +-#ENTRY_ATTRIBUTE="cn" +-#VALUE_ATTRIBUTE="nisMapEntry" +-# +-# Other common LDAP nameing +-# +-#MAP_OBJECT_CLASS="automountMap" +-#ENTRY_OBJECT_CLASS="automount" +-#MAP_ATTRIBUTE="ou" +-#ENTRY_ATTRIBUTE="cn" +-#VALUE_ATTRIBUTE="automountInformation" +-# +-#MAP_OBJECT_CLASS="automountMap" +-#ENTRY_OBJECT_CLASS="automount" +-#MAP_ATTRIBUTE="automountMapName" +-#ENTRY_ATTRIBUTE="automountKey" +-#VALUE_ATTRIBUTE="automountInformation" +-# +-# AUTH_CONF_FILE - set the default location for the SASL +-# authentication configuration file. +-# +-#AUTH_CONF_FILE="@@autofsmapdir@@/autofs_ldap_auth.conf" +-# +-# MAP_HASH_TABLE_SIZE - set the map cache hash table size. +-# Should be a power of 2 with a ratio roughly +-# between 1:10 and 1:20 for each map. +-# +-#MAP_HASH_TABLE_SIZE=1024 +-# +-# General global options +-# +-# If the kernel supports using the autofs miscellanous device +-# and you wish to use it you must set this configuration option +-# to "yes" otherwise it will not be used. +-USE_MISC_DEVICE="yes" +-# +-#OPTIONS="" +-# +--- autofs-5.0.7.orig/samples/Makefile ++++ autofs-5.0.7/samples/Makefile +@@ -4,7 +4,7 @@ include ../Makefile.rules + + SAMPLES = auto.master auto.misc auto.net auto.smb + +-all: rc.autofs autofs.conf.default autofs.service ++all: rc.autofs autofs.conf.default autofs.init.conf autofs.service + + rc.autofs: rc.autofs.in + sed -e "s|@@sbindir@@|$(sbindir)|g" \ +@@ -46,26 +46,52 @@ else + endif + endif + +-CONFIG = $(shell test -e $(INSTALLROOT)$(autofsconfdir)/autofs.orig || echo "-b --suffix=.orig") +-CEXISTS = $(shell test -e $(INSTALLROOT)$(autofsconfdir)/autofs || echo "no") ++# ++# The map directory contains the main autofs configuration ... ++# ++CONFIG = $(shell test -e $(INSTALLROOT)$(autofsmapdir)/autofs.conf.orig || echo "-b --suffix=.orig") ++CEXISTS = $(shell test -e $(INSTALLROOT)$(autofsmapdir)/autofs || echo "no") + + .PHONY: autofs.conf + autofs.conf: autofs.conf.default + @echo +- @echo "Installing autofs default configuation in $(autofsconfdir)" ++ @echo "Installing autofs default configuation in $(autofsmapdir)" + @if test -z "$(CONFIG)" ; \ + then \ + install -v autofs.conf.default -m 644 \ +- $(INSTALLROOT)$(autofsconfdir)/autofs.conf.new ; \ ++ $(INSTALLROOT)$(autofsmapdir)/autofs.conf.new ; \ + echo "Found existing backup of configuration file." ; \ + echo "Installed package default configuration file as \"autofs.conf.new\"." ; \ + else \ + install -v autofs.conf.default -m 644 $(CONFIG) \ +- $(INSTALLROOT)$(autofsconfdir)/autofs ; \ +- echo "Installed package configuration configuration as \"autofs\"." ; \ ++ $(INSTALLROOT)$(autofsmapdir)/autofs.conf ; \ ++ echo "Installed package default configuration as \"autofs.conf\"." ; \ + if test -z "$(CEXISTS)" ; \ + then \ +- echo "Backup of existing configuration made to \"autofs.orig\"." ; \ ++ echo "Backup of existing configuration made to \"autofs.conf.orig\"." ; \ ++ fi ; \ ++ fi ++ ++CINIT = $(shell test -e $(INSTALLROOT)$(autofsconfdir)/autofs.orig || echo "-b --suffix=.orig") ++CIEXISTS = $(shell test -e $(INSTALLROOT)$(autofsconfdir)/autofs || echo "no") ++ ++.PHONY: autofs.sysinit ++autofs.sysinit: autofs.init.conf ++ @echo ++ @echo "Installing autofs init configuation in $(autofsconfdir)" ++ @if test -z "$(CINIT)" ; \ ++ then \ ++ install -v autofs.init.conf -m 644 \ ++ $(INSTALLROOT)$(autofsconfdir)/autofs.new ; \ ++ echo "Found existing backup of init configuration file." ; \ ++ echo "Installed package init configuration file as \"autofs.new\"." ; \ ++ else \ ++ install -v autofs.init.conf -m 644 $(CINIT) \ ++ $(INSTALLROOT)$(autofsconfdir)/autofs ; \ ++ echo "Installed package init configuration as \"autofs\"." ; \ ++ if test -z "$(CIEXISTS)" ; \ ++ then \ ++ echo "Backup of existing init configuration made to \"autofs.orig\"." ; \ + fi ; \ + fi + +@@ -185,7 +211,7 @@ auto.smb: + fi + + install: rc.autofs autofs.conf.default dirs autofs.init autofs.service \ +- autofs.conf autofs_ldap_auth.conf $(SAMPLES) ++ autofs.conf autofs.sysinit autofs_ldap_auth.conf $(SAMPLES) + @echo + + clean: +--- autofs-5.0.7.orig/samples/autofs.conf.default.in ++++ autofs-5.0.7/samples/autofs.conf.default.in +@@ -1,23 +1,25 @@ + # + # Define default options for autofs. + # +-# MASTER_MAP_NAME - default map name for the master map. ++[ autofs ] + # +-#MASTER_MAP_NAME="auto.master" ++# master_map_name - default map name for the master map. + # +-# TIMEOUT - set the default mount timeout in secons. The internal ++#master_map_name = auto.master ++# ++# timeout - set the default mount timeout in secons. The internal + # program default is 10 minutes, but the default installed + # configuration overrides this and sets the timeout to 5 + # minutes to be consistent with earlier autofs releases. + # +-TIMEOUT=300 ++timeout = 300 + # +-# NEGATIVE_TIMEOUT - set the default negative timeout for ++# negative_timeout - set the default negative timeout for + # failed mount attempts (default 60). + # +-#NEGATIVE_TIMEOUT=60 ++#negative_timeout = 60 + # +-# MOUNT_WAIT - time to wait for a response from mount(8). ++# mount_wait - time to wait for a response from mount(8). + # Setting this timeout can cause problems when + # mount would otherwise wait for a server that + # is temporarily unavailable, such as when it's +@@ -25,34 +27,36 @@ TIMEOUT=300 + # for mount(8) usually results in a wait of around + # 3 minutes. + # +-#MOUNT_WAIT=-1 ++#mount_wait = -1 + # +-# UMOUNT_WAIT - time to wait for a response from umount(8). ++# umount_wait - time to wait for a response from umount(8). + # +-#UMOUNT_WAIT=12 ++#umount_wait = 12 + # +-# BROWSE_MODE - maps are browsable by default. ++# browse_mode - maps are browsable by default. + # +-BROWSE_MODE="no" ++browse_mode = no + # +-# MOUNT_NFS_DEFAULT_PROTOCOL - specify the default protocol used by ++# mount_nfs_default_protocol - specify the default protocol used by + # mount.nfs(8). Since we can't identify + # the default automatically we need to + # set it in our configuration. + # +-#MOUNT_NFS_DEFAULT_PROTOCOL=3 ++#mount_nfs_default_protocol = 3 ++# ++# append_options - append to global options instead of replace. + # +-# APPEND_OPTIONS - append to global options instead of replace. ++#append_options = yes + # +-#APPEND_OPTIONS="yes" ++# logging - set default log level "none", "verbose" or "debug" + # +-# LOGGING - set default log level "none", "verbose" or "debug" ++#logging = none + # +-#LOGGING="none" ++# Define base dn for map dn lookup. + # + # Define server URIs + # +-# LDAP_URI - space seperated list of server uris of the form ++# ldap_uri - space seperated list of server uris of the form + # ://[/] where can be ldap + # or ldaps. The option can be given multiple times. + # Map entries that include a server name override +@@ -69,24 +73,22 @@ BROWSE_MODE="no" + # the minimum ttl found in the SRV RR records or + # after one hour, whichever is less. + # +-#LDAP_URI="" ++#ldap_uri = "" + # +-# LDAP__TIMEOUT - timeout value for the synchronous API calls ++# ldap_timeout - timeout value for the synchronous API calls + # (default is LDAP library default). + # +-#LDAP_TIMEOUT=-1 +-# +-# LDAP_NETWORK_TIMEOUT - set the network response timeout (default 8). ++#ldap_timeout = -1 + # +-#LDAP_NETWORK_TIMEOUT=8 ++# ldap_network_timeout - set the network response timeout (default 8). + # +-# Define base dn for map dn lookup. ++#ldap_network_timeout = 8 + # +-# SEARCH_BASE - base dn to use for searching for map search dn. ++# search_base - base dn to use for searching for map search dn. + # Multiple entries can be given and they are checked + # in the order they occur here. + # +-#SEARCH_BASE="" ++#search_base = "" + # + # Define the LDAP schema to used for lookups + # +@@ -95,43 +97,34 @@ BROWSE_MODE="no" + # basdn for lookups. If you want to minimize the number of + # queries to the server set the values here. + # +-#MAP_OBJECT_CLASS="nisMap" +-#ENTRY_OBJECT_CLASS="nisObject" +-#MAP_ATTRIBUTE="nisMapName" +-#ENTRY_ATTRIBUTE="cn" +-#VALUE_ATTRIBUTE="nisMapEntry" ++#map_object_class = nisMap ++#entry_object_class = nisObject ++#map_attribute = nisMapName ++#entry_attribute = cn ++#value_attribute= nisMapEntry + # + # Other common LDAP nameing + # +-#MAP_OBJECT_CLASS="automountMap" +-#ENTRY_OBJECT_CLASS="automount" +-#MAP_ATTRIBUTE="ou" +-#ENTRY_ATTRIBUTE="cn" +-#VALUE_ATTRIBUTE="automountInformation" +-# +-#MAP_OBJECT_CLASS="automountMap" +-#ENTRY_OBJECT_CLASS="automount" +-#MAP_ATTRIBUTE="automountMapName" +-#ENTRY_ATTRIBUTE="automountKey" +-#VALUE_ATTRIBUTE="automountInformation" ++#map_object_class = automountMap ++#entry_object_class = automount ++#map_attribute = ou ++#entry_attribute = cn ++#value_attribute= automountInformation ++# ++#map_object_class = automountMap ++#entry_object_class = automount ++#map_attribute = automountMapName ++#entry_attribute = automountKey ++#value_attribute= automountInformation + # +-# AUTH_CONF_FILE - set the default location for the SASL +-# authentication configuration file. ++# auth_conf_file - set the default location for the SASL ++# authentication configuration file. + # +-#AUTH_CONF_FILE="@@autofsmapdir@@/autofs_ldap_auth.conf" ++#auth_conf_file = @@autofsmapdir@@/autofs_ldap_auth.conf + # +-# MAP_HASH_TABLE_SIZE - set the map cache hash table size. ++# map_hash_table_size - set the map cache hash table size. + # Should be a power of 2 with a ratio roughly + # between 1:10 and 1:20 for each map. + # +-#MAP_HASH_TABLE_SIZE=1024 +-# +-# General global options +-# +-# If the kernel supports using the autofs miscellanous device +-# and you wish to use it you must set this configuration option +-# to "yes" otherwise it will not be used. +-USE_MISC_DEVICE="yes" +-# +-#OPTIONS="" ++#map_hash_table_size = 1024 + # +--- /dev/null ++++ autofs-5.0.7/samples/autofs.init.conf +@@ -0,0 +1,14 @@ ++# ++# Init syatem options ++# ++# If the kernel supports using the autofs miscellanous device ++# and you wish to use it you must set this configuration option ++# to "yes" otherwise it will not be used. ++# ++USE_MISC_DEVICE="yes" ++# ++# Use OPTIONS to add automount(8) command line options that ++# will be used when the daemon is started. ++# ++#OPTIONS="" ++# diff --git a/SOURCES/autofs-5.0.9-amd-lookup-try-to-use-external-mounts-for-nfs-mounts.patch b/SOURCES/autofs-5.0.9-amd-lookup-try-to-use-external-mounts-for-nfs-mounts.patch new file mode 100644 index 0000000..dc52861 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-try-to-use-external-mounts-for-nfs-mounts.patch @@ -0,0 +1,38 @@ +autofs-5.0.9 - amd lookup try to use external mounts for nfs mounts + +From: Ian Kent + +When using nfs type mounts they may be mounted externally to avoid +multiple instances of the mount. + +The current usage doesn't always use external mounts when it can so, +if option fs is defined, use an external. +--- + modules/parse_amd.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 0c708e6..becc519 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -1011,7 +1011,7 @@ static int do_nfs_mount(struct autofs_point *ap, const char *name, + if (proximity == PROXIMITY_OTHER && entry->remopts) + opts = entry->remopts; + +- if (!entry->sublink) { ++ if (!entry->fs) { + ret = mount_nfs->mount_mount(ap, ap->path, name, strlen(name), + target, entry->type, opts, + mount_nfs->context); +@@ -1214,6 +1214,11 @@ static unsigned int validate_nfs_options(unsigned int logopt, + return 0; + } + } ++ if (entry->sublink && !entry->fs) { ++ error(logopt, MODPREFIX ++ "%s: sublink option requires option fs"); ++ return 0; ++ } + return 1; + } + diff --git a/SOURCES/autofs-5.0.9-amd-lookup-try-to-use-external-mounts-for-real-mounts.patch b/SOURCES/autofs-5.0.9-amd-lookup-try-to-use-external-mounts-for-real-mounts.patch new file mode 100644 index 0000000..5904ba9 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-try-to-use-external-mounts-for-real-mounts.patch @@ -0,0 +1,47 @@ +autofs-5.0.9 - amd lookup try to use external mounts for real mounts + +From: Ian Kent + +When using generic type mounts they may point to user mounted +external mounts which doesn't need to be mounted or umounted. + +The current usage doesn't always use external mounts which isn't +quite right so, if option fs is defined use, an external. +--- + modules/parse_amd.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 410f6ff..790f25e 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -970,7 +970,7 @@ static int do_generic_mount(struct autofs_point *ap, const char *name, + unsigned int umount = 0; + int ret = 0; + +- if (!entry->sublink) { ++ if (!entry->fs) { + ret = do_mount(ap, ap->path, name, strlen(name), + target, entry->type, entry->opts); + } else { +@@ -986,7 +986,7 @@ static int do_generic_mount(struct autofs_point *ap, const char *name, + goto out; + umount = 1; + } +- /* We might be using an external mount */ ++ /* We have an external mount */ + ext_mount_add(&entry->ext_mount, entry->fs, umount); + ret = do_link_mount(ap, name, entry, flags); + } +@@ -1237,6 +1237,11 @@ static unsigned int validate_generic_options(unsigned int logopt, + return 0; + } + } ++ if (entry->sublink && !entry->fs) { ++ error(logopt, MODPREFIX ++ "%s: sublink option requires option fs"); ++ return 0; ++ } + return 1; + } + diff --git a/SOURCES/autofs-5.0.9-amd-lookup-update-changelog.patch b/SOURCES/autofs-5.0.9-amd-lookup-update-changelog.patch new file mode 100644 index 0000000..c6e42aa --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-update-changelog.patch @@ -0,0 +1,19 @@ +autofs-5.0.9 - amd lookup update changelog + +From: Ian Kent + + +--- + CHANGELOG | 1 + + 1 file changed, 1 insertion(+) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -108,6 +108,7 @@ + - fix crash due to thread unsafe use of libldap. + - fix deadlock in init_ldap_connection. + - extend fix for crash due to thread unsafe use of libldap. ++- add amd map format parser. + + 25/07/2012 autofs-5.0.7 + ======================= diff --git a/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-file-to-handle-amd-keys.patch b/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-file-to-handle-amd-keys.patch new file mode 100644 index 0000000..07ca05b --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-file-to-handle-amd-keys.patch @@ -0,0 +1,410 @@ +autofs-5.0.9 - amd lookup update lookup file to handle amd keys + +From: Ian Kent + +Update file map lookup to handle map key matching for amd format +maps. +--- + modules/lookup_file.c | 287 +++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 206 insertions(+), 81 deletions(-) + +diff --git a/modules/lookup_file.c b/modules/lookup_file.c +index 512e3ef..7c982c6 100644 +--- a/modules/lookup_file.c ++++ b/modules/lookup_file.c +@@ -702,9 +702,22 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + } else { + char *s_key; + +- s_key = sanitize_path(key, k_len, ap->type, ap->logopt); +- if (!s_key) +- continue; ++ if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ if (!strcmp(key, "/defaults")) { ++ cache_writelock(mc); ++ cache_update(mc, source, key, mapent, age); ++ cache_unlock(mc); ++ continue; ++ } ++ /* Don't fail on "/" in key => type == 0 */ ++ s_key = sanitize_path(key, k_len, 0, ap->logopt); ++ if (!s_key) ++ continue; ++ } else { ++ s_key = sanitize_path(key, k_len, ap->type, ap->logopt); ++ if (!s_key) ++ continue; ++ } + + cache_writelock(mc); + cache_update(mc, source, s_key, mapent, age); +@@ -724,12 +737,75 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + return NSS_STATUS_SUCCESS; + } + ++static int match_key(struct autofs_point *ap, ++ struct map_source *source, char *map_key, ++ const char *key, size_t key_len, const char *mapent) ++{ ++ char buf[MAX_ERR_BUF]; ++ struct mapent_cache *mc; ++ time_t age = time(NULL); ++ char *lkp_key; ++ char *prefix; ++ size_t map_key_len; ++ int ret, eq; ++ ++ mc = source->mc; ++ ++ /* exact match is a match for both autofs and amd */ ++ eq = strcmp(map_key, key); ++ if (eq == 0) { ++ cache_writelock(mc); ++ ret = cache_update(mc, source, key, mapent, age); ++ cache_unlock(mc); ++ return ret; ++ } ++ ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) ++ return CHE_FAIL; ++ ++ map_key_len = strlen(map_key); ++ ++ lkp_key = strdup(key); ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "strdup: %s", estr); ++ return CHE_FAIL; ++ } ++ ++ ret = CHE_FAIL; ++ ++ if (map_key_len > (strlen(lkp_key) + 2)) ++ goto done; ++ ++ /* ++ * Now strip successive directory components and try a ++ * match against map entries ending with a wildcard and ++ * finally try the wilcard entry itself. If we get a match ++ * then update the cache with the read key and its mapent. ++ */ ++ while ((prefix = strrchr(lkp_key, '/'))) { ++ size_t len; ++ *prefix = '\0'; ++ len = strlen(lkp_key); ++ eq = strncmp(map_key, lkp_key, len); ++ if (!eq && map_key[len + 1] == '*') { ++ cache_writelock(mc); ++ ret = cache_update(mc, source, map_key, mapent, age); ++ cache_unlock(mc); ++ goto done; ++ } ++ } ++done: ++ free(lkp_key); ++ return ret; ++} ++ + static int lookup_one(struct autofs_point *ap, + struct map_source *source, + const char *key, int key_len, + struct lookup_context *ctxt) + { +- struct mapent_cache *mc; ++ struct mapent_cache *mc = source->mc; + char mkey[KEY_MAX_LEN + 1]; + char mapent[MAPENT_MAX_LEN + 1]; + time_t age = time(NULL); +@@ -737,8 +813,6 @@ static int lookup_one(struct autofs_point *ap, + unsigned int k_len, m_len; + int entry, ret; + +- mc = source->mc; +- + f = open_fopen_r(ctxt->mapname); + if (!f) { + error(ap->logopt, +@@ -781,29 +855,38 @@ static int lookup_one(struct autofs_point *ap, + } + } else { + char *s_key; +- int eq; + +- s_key = sanitize_path(mkey, k_len, ap->type, ap->logopt); +- if (!s_key) +- continue; ++ if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ if (!strcmp(mkey, "/defaults")) { ++ cache_writelock(mc); ++ cache_update(mc, source, mkey, mapent, age); ++ cache_unlock(mc); ++ continue; ++ } ++ /* Don't fail on "/" in key => type == 0 */ ++ s_key = sanitize_path(mkey, k_len, 0, ap->logopt); ++ if (!s_key) ++ continue; ++ } else { ++ s_key = sanitize_path(mkey, k_len, ap->type, ap->logopt); ++ if (!s_key) ++ continue; + +- if (key_len != strlen(s_key)) { +- free(s_key); +- continue; ++ if (key_len != strlen(s_key)) { ++ free(s_key); ++ continue; ++ } + } + +- eq = strncmp(s_key, key, key_len); +- if (eq != 0) { ++ ret = match_key(ap, source, ++ s_key, key, key_len, mapent); ++ if (ret == CHE_FAIL) { + free(s_key); + continue; + } + + free(s_key); + +- cache_writelock(mc); +- ret = cache_update(mc, source, key, mapent, age); +- cache_unlock(mc); +- + fclose(f); + + return ret; +@@ -897,7 +980,10 @@ static int check_map_indirect(struct autofs_point *ap, + return NSS_STATUS_NOTFOUND; + + cache_writelock(mc); +- exists = cache_lookup_distinct(mc, key); ++ if (source->flags & MAP_FLAG_FORMAT_AMD) ++ exists = match_cached_key(ap, MODPREFIX, source, key); ++ else ++ exists = cache_lookup_distinct(mc, key); + /* Not found in the map but found in the cache */ + if (exists && exists->source == source && ret & CHE_MISSING) { + if (exists->mapent) { +@@ -936,6 +1022,53 @@ static int check_map_indirect(struct autofs_point *ap, + return NSS_STATUS_SUCCESS; + } + ++static int map_update_needed(struct autofs_point *ap, ++ struct map_source *source, ++ struct lookup_context * ctxt) ++{ ++ struct mapent_cache *mc; ++ struct mapent *me; ++ struct stat st; ++ int ret = 1; ++ ++ mc = source->mc; ++ ++ /* ++ * We can skip the map lookup and cache update altogether ++ * if we know the map hasn't been modified since it was ++ * last read. If it has then we can mark the map stale ++ * so a re-read is triggered following the lookup. ++ */ ++ if (stat(ctxt->mapname, &st)) { ++ error(ap->logopt, MODPREFIX ++ "file map %s, could not stat", ctxt->mapname); ++ return -1; ++ } ++ ++ cache_readlock(mc); ++ me = cache_lookup_first(mc); ++ if (me && st.st_mtime <= me->age) { ++ /* ++ * If any map instances are present for this source ++ * then either we have plus included entries or we ++ * are looking through the list of nsswitch sources. ++ * In either case, or if it's a "multi" source, we ++ * cannot avoid reading through the map because we ++ * must preserve the key order over multiple sources ++ * or maps. But also, we can't know, at this point, ++ * if a source instance has been changed since the ++ * last time we checked it. ++ */ ++ if (!source->instance && ++ source->type && strcmp(source->type, "multi")) ++ ret = 0; ++ } else ++ source->stale = 1; ++ cache_unlock(mc); ++ ++ return ret; ++} ++ + int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) + { + struct lookup_context *ctxt = (struct lookup_context *) context; +@@ -944,8 +1077,10 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + struct mapent *me; + char key[KEY_MAX_LEN + 1]; + int key_len; ++ char *lkp_key; + char *mapent = NULL; + char mapent_buf[MAPENT_MAX_LEN + 1]; ++ char buf[MAX_ERR_BUF]; + int status = 0; + int ret = 1; + +@@ -967,9 +1102,18 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + + debug(ap->logopt, MODPREFIX "looking up %s", name); + +- key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); +- if (key_len > KEY_MAX_LEN) +- return NSS_STATUS_NOTFOUND; ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { ++ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); ++ if (key_len > KEY_MAX_LEN) ++ return NSS_STATUS_NOTFOUND; ++ } else { ++ key_len = expandamdent(name, NULL, NULL); ++ if (key_len > KEY_MAX_LEN) ++ return NSS_STATUS_NOTFOUND; ++ memset(key, 0, KEY_MAX_LEN + 1); ++ expandamdent(name, key, NULL); ++ debug(ap->logopt, MODPREFIX "expanded key: \"%s\"", key); ++ } + + /* Check if we recorded a mount fail for this key anywhere */ + me = lookup_source_mapent(ap, key, LKP_DISTINCT); +@@ -1003,50 +1147,35 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + * we never know about it. + */ + if (ap->type == LKP_INDIRECT && *key != '/') { +- struct stat st; +- char *lkp_key; ++ int ret; + +- /* +- * We can skip the map lookup and cache update altogether +- * if we know the map hasn't been modified since it was +- * last read. If it has then we can mark the map stale +- * so a re-read is triggered following the lookup. +- */ +- if (stat(ctxt->mapname, &st)) { +- error(ap->logopt, MODPREFIX +- "file map %s, could not stat", ctxt->mapname); +- return NSS_STATUS_UNAVAIL; +- } ++ ret = map_update_needed(ap, source, ctxt); ++ if (!ret) ++ goto do_cache_lookup; ++ /* Map isn't accessable, just try the cache */ ++ if (ret < 0) ++ goto do_cache_lookup; + + cache_readlock(mc); +- me = cache_lookup_first(mc); +- if (me && st.st_mtime <= me->age) { +- /* +- * If any map instances are present for this source +- * then either we have plus included entries or we +- * are looking through the list of nsswitch sources. +- * In either case, or if it's a "multi" source, we +- * cannot avoid reading through the map because we +- * must preserve the key order over multiple sources +- * or maps. But also, we can't know, at this point, +- * if a source instance has been changed since the +- * last time we checked it. +- */ +- if (!source->instance && +- source->type && strcmp(source->type, "multi")) +- goto do_cache_lookup; +- } else +- source->stale = 1; +- + me = cache_lookup_distinct(mc, key); + if (me && me->multi) + lkp_key = strdup(me->multi->key); +- else ++ else if (!ap->pref) + lkp_key = strdup(key); ++ else { ++ lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1); ++ if (lkp_key) { ++ strcpy(lkp_key, ap->pref); ++ strcat(lkp_key, key); ++ } ++ } + cache_unlock(mc); + +- if (!lkp_key) ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); + return NSS_STATUS_UNKNOWN; ++ } + + status = check_map_indirect(ap, source, + lkp_key, strlen(lkp_key), ctxt); +@@ -1066,42 +1195,38 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + * when we're starting up so just take the readlock in that + * case. + */ ++do_cache_lookup: + if (ap->flags & MOUNT_FLAG_REMOUNT) + cache_readlock(mc); + else + cache_writelock(mc); +-do_cache_lookup: +- me = cache_lookup(mc, key); +- /* +- * Stale mapent => check for entry in alternate source or wildcard. +- * Note, plus included direct mount map entries are included as an +- * instance (same map entry cache), not in a distinct source. +- */ +- if (me && (!me->mapent || +- (me->source != source && *me->key != '/'))) { +- while ((me = cache_lookup_key_next(me))) +- if (me->source == source) +- break; +- if (!me) +- me = cache_lookup_distinct(mc, "*"); ++ ++ if (!ap->pref) ++ lkp_key = strdup(key); ++ else { ++ lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1); ++ if (lkp_key) { ++ strcpy(lkp_key, ap->pref); ++ strcat(lkp_key, key); ++ } ++ } ++ ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ cache_unlock(mc); ++ return NSS_STATUS_UNKNOWN; + } ++ ++ me = match_cached_key(ap, MODPREFIX, source, lkp_key); + if (me && me->mapent) { +- /* +- * If this is a lookup add wildcard match for later validation +- * checks and negative cache lookups. +- */ +- if (!(ap->flags & MOUNT_FLAG_REMOUNT) && +- ap->type == LKP_INDIRECT && *me->key == '*') { +- ret = cache_update(mc, source, key, me->mapent, me->age); +- if (!(ret & (CHE_OK | CHE_UPDATED))) +- me = NULL; +- } + if (me && (me->source == source || *me->key == '/')) { + strcpy(mapent_buf, me->mapent); + mapent = mapent_buf; + } + } + cache_unlock(mc); ++ free(lkp_key); + + if (!me) + return NSS_STATUS_NOTFOUND; diff --git a/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-nisplus-to-handle-amd-keys.patch b/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-nisplus-to-handle-amd-keys.patch new file mode 100644 index 0000000..d88a8ea --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-nisplus-to-handle-amd-keys.patch @@ -0,0 +1,314 @@ +autofs-5.0.9 - amd lookup update lookup nisplus to handle amd keys + +From: Ian Kent + + +--- + modules/lookup_nisplus.c | 208 +++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 196 insertions(+), 12 deletions(-) + +diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c +index 42c9ccc..e9444c9 100644 +--- a/modules/lookup_nisplus.c ++++ b/modules/lookup_nisplus.c +@@ -243,7 +243,19 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + if (*key == '+') + continue; + +- s_key = sanitize_path(key, len, ap->type, ap->logopt); ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) ++ s_key = sanitize_path(key, len, ap->type, ap->logopt); ++ else { ++ if (!strcmp(key, "/defaults")) { ++ mapent = ENTRY_VAL(this, 1); ++ cache_writelock(mc); ++ cache_update(mc, source, key, mapent, age); ++ cache_unlock(mc); ++ continue; ++ } ++ /* Don't fail on "/" in key => type == 0 */ ++ s_key = sanitize_path(key, len, 0, ap->logopt); ++ } + if (!s_key) + continue; + +@@ -322,6 +334,66 @@ static int lookup_one(struct autofs_point *ap, + return ret; + } + ++static int match_key(struct autofs_point *ap, ++ struct map_source *source, ++ const char *key, int key_len, ++ struct lookup_context *ctxt) ++{ ++ char buf[MAX_ERR_BUF]; ++ char *lkp_key; ++ char *prefix; ++ int ret; ++ ++ ret = lookup_one(ap, source, key, key_len, ctxt); ++ if (ret < 0) ++ return ret; ++ if (ret == CHE_OK || ret == CHE_UPDATED) ++ return ret; ++ ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) ++ return CHE_FAIL; ++ ++ lkp_key = strdup(key); ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "strdup: %s", estr); ++ return CHE_FAIL; ++ } ++ ++ ret = CHE_MISSING; ++ ++ /* ++ * Now strip successive directory components and try a ++ * match against map entries ending with a wildcard and ++ * finally try the wilcard entry itself. ++ */ ++ while ((prefix = strrchr(lkp_key, '/'))) { ++ char *match; ++ size_t len; ++ *prefix = '\0'; ++ len = strlen(lkp_key) + 3; ++ match = malloc(len); ++ if (!match) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ ret = CHE_FAIL; ++ goto done; ++ } ++ len--; ++ strcpy(match, lkp_key); ++ strcat(match, "/*"); ++ ret = lookup_one(ap, source, match, len, ctxt); ++ free(match); ++ if (ret < 0) ++ goto done; ++ if (ret == CHE_OK || ret == CHE_UPDATED) ++ goto done; ++ } ++done: ++ free(lkp_key); ++ return ret; ++} ++ + static int lookup_wild(struct autofs_point *ap, + struct map_source *source, struct lookup_context *ctxt) + { +@@ -374,6 +446,59 @@ static int lookup_wild(struct autofs_point *ap, + return ret; + } + ++static int lookup_amd_defaults(struct autofs_point *ap, ++ struct map_source *source, ++ struct lookup_context *ctxt) ++{ ++ struct mapent_cache *mc = source->mc; ++ char *tablename; ++ nis_result *result; ++ nis_object *this; ++ char *mapent; ++ char buf[MAX_ERR_BUF]; ++ int cur_state; ++ int ret; ++ ++ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); ++ tablename = malloc(9 + strlen(ctxt->mapname) + ++ strlen(ctxt->domainname) + 20); ++ if (!tablename) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ logerr(MODPREFIX "malloc: %s", estr); ++ pthread_setcancelstate(cur_state, NULL); ++ return CHE_FAIL; ++ } ++ sprintf(tablename, "[key=/defaults],%s.org_dir.%s", ++ ctxt->mapname, ctxt->domainname); ++ ++ result = nis_list(tablename, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); ++ if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) { ++ nis_error rs = result->status; ++ nis_freeresult(result); ++ free(tablename); ++ pthread_setcancelstate(cur_state, NULL); ++ if (rs == NIS_NOTFOUND || ++ rs == NIS_S_NOTFOUND || ++ rs == NIS_PARTIAL) ++ return CHE_MISSING; ++ ++ return -rs; ++ } ++ ++ this = NIS_RES_OBJECT(result); ++ mapent = ENTRY_VAL(this, 1); ++ ++ cache_writelock(mc); ++ ret = cache_update(mc, source, "/defaults", mapent, time(NULL)); ++ cache_unlock(mc); ++ ++ nis_freeresult(result); ++ free(tablename); ++ pthread_setcancelstate(cur_state, NULL); ++ ++ return ret; ++} ++ + static int check_map_indirect(struct autofs_point *ap, + struct map_source *source, + char *key, int key_len, +@@ -387,8 +512,17 @@ static int check_map_indirect(struct autofs_point *ap, + + mc = source->mc; + ++ if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ /* Check for a /defaults entry to update the map source */ ++ if (lookup_amd_defaults(ap, source, ctxt) == CHE_FAIL) { ++ warn(ap->logopt, MODPREFIX ++ "error getting /defaults from map %s", ++ ctxt->mapname); ++ } ++ } ++ + /* check map and if change is detected re-read map */ +- ret = lookup_one(ap, source, key, key_len, ctxt); ++ ret = match_key(ap, source, key, key_len, ctxt); + if (ret == CHE_FAIL) + return NSS_STATUS_NOTFOUND; + +@@ -397,9 +531,16 @@ static int check_map_indirect(struct autofs_point *ap, + * If the server is down and the entry exists in the cache + * and belongs to this map return success and use the entry. + */ +- exists = cache_lookup(mc, key); +- if (exists && exists->source == source) ++ cache_readlock(mc); ++ if (source->flags & MAP_FLAG_FORMAT_AMD) ++ exists = match_cached_key(ap, MODPREFIX, source, key); ++ else ++ exists = cache_lookup(mc, key); ++ if (exists && exists->source == source) { ++ cache_unlock(mc); + return NSS_STATUS_SUCCESS; ++ } ++ cache_unlock(mc); + + warn(ap->logopt, + MODPREFIX "lookup for %s failed: %s", +@@ -418,6 +559,10 @@ static int check_map_indirect(struct autofs_point *ap, + } + me = cache_lookup_next(mc, me); + } ++ if (source->flags & MAP_FLAG_FORMAT_AMD) ++ exists = match_cached_key(ap, MODPREFIX, source, key); ++ else ++ exists = cache_lookup_distinct(mc, key); + exists = cache_lookup_distinct(mc, key); + /* Not found in the map but found in the cache */ + if (exists && exists->source == source && ret & CHE_MISSING) { +@@ -474,9 +619,11 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + struct mapent_cache *mc; + char key[KEY_MAX_LEN + 1]; + int key_len; ++ char *lkp_key; + char *mapent = NULL; + int mapent_len; + struct mapent *me; ++ char buf[MAX_ERR_BUF]; + int status; + int ret = 1; + +@@ -488,9 +635,18 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + + debug(ap->logopt, MODPREFIX "looking up %s", name); + +- key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); +- if (key_len > KEY_MAX_LEN) +- return NSS_STATUS_NOTFOUND; ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { ++ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); ++ if (key_len > KEY_MAX_LEN) ++ return NSS_STATUS_NOTFOUND; ++ } else { ++ key_len = expandamdent(name, NULL, NULL); ++ if (key_len > KEY_MAX_LEN) ++ return NSS_STATUS_NOTFOUND; ++ memset(key, 0, KEY_MAX_LEN + 1); ++ expandamdent(name, key, NULL); ++ debug(ap->logopt, MODPREFIX "expanded key: \"%s\"", key); ++ } + + /* Check if we recorded a mount fail for this key anywhere */ + me = lookup_source_mapent(ap, key, LKP_DISTINCT); +@@ -524,21 +680,30 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + * we never know about it. + */ + if (ap->type == LKP_INDIRECT && *key != '/') { +- char *lkp_key; +- + cache_readlock(mc); + me = cache_lookup_distinct(mc, key); + if (me && me->multi) + lkp_key = strdup(me->multi->key); +- else ++ else if (!ap->pref) + lkp_key = strdup(key); ++ else { ++ lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1); ++ if (lkp_key) { ++ strcpy(lkp_key, ap->pref); ++ strcat(lkp_key, key); ++ } ++ } + cache_unlock(mc); + +- if (!lkp_key) ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); + return NSS_STATUS_UNKNOWN; ++ } + + status = check_map_indirect(ap, source, + lkp_key, strlen(lkp_key), ctxt); ++ free(lkp_key); + if (status) + return status; + } +@@ -555,7 +720,25 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + cache_readlock(mc); + else + cache_writelock(mc); +- me = cache_lookup(mc, key); ++ ++ if (!ap->pref) ++ lkp_key = strdup(key); ++ else { ++ lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1); ++ if (lkp_key) { ++ strcpy(lkp_key, ap->pref); ++ strcat(lkp_key, key); ++ } ++ } ++ ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ cache_unlock(mc); ++ return NSS_STATUS_UNKNOWN; ++ } ++ ++ me = match_cached_key(ap, MODPREFIX, source, lkp_key); + /* Stale mapent => check for entry in alternate source or wildcard */ + if (me && !me->mapent) { + while ((me = cache_lookup_key_next(me))) +@@ -583,6 +766,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + } + } + cache_unlock(mc); ++ free(lkp_key); + + if (!mapent) + return NSS_STATUS_TRYAGAIN; diff --git a/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-program-to-handle-amd-keys.patch b/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-program-to-handle-amd-keys.patch new file mode 100644 index 0000000..9c21bf7 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-program-to-handle-amd-keys.patch @@ -0,0 +1,462 @@ +autofs-5.0.9 - amd lookup update lookup program to handle amd keys + +From: Ian Kent + + +--- + modules/lookup_program.c | 390 +++++++++++++++++++++++++++++++++------------- + 1 file changed, 282 insertions(+), 108 deletions(-) + +diff --git a/modules/lookup_program.c b/modules/lookup_program.c +index 6ce94e4..08d14ff 100644 +--- a/modules/lookup_program.c ++++ b/modules/lookup_program.c +@@ -113,123 +113,30 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + return NSS_STATUS_UNKNOWN; + } + +-int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) ++static char *lookup_one(struct autofs_point *ap, ++ const char *name, int name_len, ++ struct lookup_context *ctxt) + { +- struct lookup_context *ctxt = (struct lookup_context *) context; +- struct map_source *source; +- struct mapent_cache *mc; + char *mapent = NULL, *mapp, *tmp; +- struct mapent *me; + char buf[MAX_ERR_BUF]; + char errbuf[1024], *errp; + char ch; + int pipefd[2], epipefd[2]; + struct pollfd pfd[2]; + pid_t f; +- int status; + enum state { st_space, st_map, st_done } state; + int quoted = 0; +- int ret = 1; + int distance; + int alloci = 1; +- +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- +- mc = source->mc; +- +- /* Check if we recorded a mount fail for this key anywhere */ +- me = lookup_source_mapent(ap, name, LKP_DISTINCT); +- if (me) { +- if (me->status >= time(NULL)) { +- cache_unlock(me->mc); +- return NSS_STATUS_NOTFOUND; +- } else { +- struct mapent_cache *smc = me->mc; +- struct mapent *sme; +- +- if (me->mapent) +- cache_unlock(smc); +- else { +- cache_unlock(smc); +- cache_writelock(smc); +- sme = cache_lookup_distinct(smc, name); +- /* Negative timeout expired for non-existent entry. */ +- if (sme && !sme->mapent) { +- if (cache_pop_mapent(sme) == CHE_FAIL) +- cache_delete(smc, name); +- } +- cache_unlock(smc); +- } +- } +- } +- +- /* Catch installed direct offset triggers */ +- cache_readlock(mc); +- me = cache_lookup_distinct(mc, name); +- if (!me) { +- cache_unlock(mc); +- /* +- * If there's a '/' in the name and the offset is not in +- * the cache then it's not a valid path in the mount tree. +- */ +- if (strchr(name, '/')) { +- debug(ap->logopt, +- MODPREFIX "offset %s not found", name); +- return NSS_STATUS_NOTFOUND; +- } +- } else { +- /* Otherwise we found a valid offset so try mount it */ +- debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent); +- +- /* +- * If this is a request for an offset mount (whose entry +- * must be present in the cache to be valid) or the entry +- * is newer than the negative timeout value then just +- * try and mount it. Otherwise try and remove it and +- * proceed with the program map lookup. +- */ +- if (strchr(name, '/') || +- me->age + ap->negative_timeout > time(NULL)) { +- char *ent = NULL; +- +- if (me->mapent) { +- ent = alloca(strlen(me->mapent) + 1); +- strcpy(ent, me->mapent); +- } +- cache_unlock(mc); +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- ret = ctxt->parse->parse_mount(ap, name, +- name_len, ent, ctxt->parse->context); +- goto out_free; +- } else { +- if (me->multi) { +- cache_unlock(mc); +- warn(ap->logopt, MODPREFIX +- "unexpected lookup for active multi-mount" +- " key %s, returning fail", name); +- return NSS_STATUS_UNAVAIL; +- } +- cache_unlock(mc); +- cache_writelock(mc); +- me = cache_lookup_distinct(mc, name); +- if (me) +- cache_delete(mc, name); +- cache_unlock(mc); +- } +- } ++ int status; + + mapent = (char *) malloc(MAPENT_MAX_LEN + 1); + if (!mapent) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + logerr(MODPREFIX "malloc: %s", estr); +- return NSS_STATUS_UNAVAIL; ++ return NULL; + } + +- debug(ap->logopt, MODPREFIX "looking up %s", name); +- + /* + * We don't use popen because we don't want to run /bin/sh plus we + * want to send stderr to the syslog, and we don't use spawnl() +@@ -238,12 +145,12 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + if (open_pipe(pipefd)) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + logerr(MODPREFIX "pipe: %s", estr); +- goto out_free; ++ goto out_error; + } + if (open_pipe(epipefd)) { + close(pipefd[0]); + close(pipefd[1]); +- goto out_free; ++ goto out_error; + } + + f = fork(); +@@ -254,7 +161,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + close(pipefd[1]); + close(epipefd[0]); + close(epipefd[1]); +- goto out_free; ++ goto out_error; + } else if (f == 0) { + reset_signals(); + close(pipefd[0]); +@@ -420,21 +327,288 @@ next: + if (waitpid(f, &status, 0) != f) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + logerr(MODPREFIX "waitpid: %s", estr); +- goto out_free; ++ goto out_error; + } + + if (mapp == mapent || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { + info(ap->logopt, MODPREFIX "lookup for %s failed", name); +- goto out_free; ++ goto out_error; + } + +- cache_writelock(mc); +- ret = cache_update(mc, source, name, mapent, time(NULL)); +- cache_unlock(mc); +- if (ret == CHE_FAIL) { ++ return mapent; ++ ++out_error: ++ if (mapent) + free(mapent); +- return NSS_STATUS_UNAVAIL; ++ ++ return NULL; ++} ++ ++static int lookup_amd_defaults(struct autofs_point *ap, ++ struct map_source *source, ++ struct lookup_context *ctxt) ++{ ++ struct mapent_cache *mc = source->mc; ++ char *ment = lookup_one(ap, "/defaults", 9, ctxt); ++ if (ment) { ++ char *start = ment + 9; ++ int ret; ++ ++ while (isblank(*start)) ++ start++; ++ cache_writelock(mc); ++ ret = cache_update(mc, source, "/defaults", start, time(NULL)); ++ cache_unlock(mc); ++ if (ret == CHE_FAIL) { ++ free(ment); ++ return NSS_STATUS_UNAVAIL; ++ } ++ free(ment); + } ++ return NSS_STATUS_SUCCESS; ++} ++ ++static int match_key(struct autofs_point *ap, ++ struct map_source *source, ++ const char *name, int name_len, ++ char **mapent, struct lookup_context *ctxt) ++{ ++ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; ++ struct mapent_cache *mc = source->mc; ++ char buf[MAX_ERR_BUF]; ++ char *ment; ++ char *lkp_key; ++ size_t lkp_len; ++ char *prefix; ++ int ret; ++ ++ if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ ret = lookup_amd_defaults(ap, source, ctxt); ++ if (ret != NSS_STATUS_SUCCESS) { ++ warn(ap->logopt, ++ MODPREFIX "failed to save /defaults entry"); ++ } ++ } ++ ++ if (!is_amd_format) { ++ lkp_key = strdup(name); ++ lkp_len = name_len; ++ } else { ++ size_t len; ++ ++ if (ap->pref) ++ len = strlen(ap->pref) + strlen(name); ++ else ++ len = strlen(name); ++ ++ lkp_key = malloc(len + 1); ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ return NSS_STATUS_UNAVAIL; ++ } ++ ++ if (ap->pref) { ++ strcpy(lkp_key, ap->pref); ++ strcat(lkp_key, name); ++ } else ++ strcpy(lkp_key, name); ++ ++ lkp_len = len; ++ } ++ ++ ment = lookup_one(ap, lkp_key, lkp_len, ctxt); ++ if (ment) { ++ char *start = ment; ++ if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ start = ment + lkp_len; ++ while (isblank(*start)) ++ start++; ++ } ++ cache_writelock(mc); ++ ret = cache_update(mc, source, lkp_key, start, time(NULL)); ++ cache_unlock(mc); ++ if (ret == CHE_FAIL) { ++ free(ment); ++ free(lkp_key); ++ return NSS_STATUS_UNAVAIL; ++ } ++ *mapent = strdup(start); ++ if (!*mapent) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ free(lkp_key); ++ free(ment); ++ return NSS_STATUS_UNAVAIL; ++ } ++ free(lkp_key); ++ free(ment); ++ return NSS_STATUS_SUCCESS; ++ } ++ ++ if (!is_amd_format) { ++ free(lkp_key); ++ return NSS_STATUS_NOTFOUND; ++ } ++ ++ ret = NSS_STATUS_NOTFOUND; ++ ++ /* ++ * Now strip successive directory components and try a ++ * match against map entries ending with a wildcard and ++ * finally try the wilcard entry itself. ++ */ ++ while ((prefix = strrchr(lkp_key, '/'))) { ++ char *match; ++ size_t len; ++ *prefix = '\0'; ++ len = strlen(lkp_key) + 3; ++ match = malloc(len); ++ if (!match) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ free(lkp_key); ++ return NSS_STATUS_UNAVAIL; ++ } ++ len--; ++ strcpy(match, lkp_key); ++ strcat(match, "/*"); ++ ment = lookup_one(ap, match, len, ctxt); ++ if (ment) { ++ char *start = ment + len; ++ while (isblank(*start)) ++ start++; ++ cache_writelock(mc); ++ ret = cache_update(mc, source, match, start, time(NULL)); ++ cache_unlock(mc); ++ if (ret == CHE_FAIL) { ++ free(match); ++ free(ment); ++ free(lkp_key); ++ return NSS_STATUS_UNAVAIL; ++ } ++ free(match); ++ *mapent = strdup(start); ++ if (!*mapent) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ free(ment); ++ free(lkp_key); ++ return NSS_STATUS_UNAVAIL; ++ } ++ free(ment); ++ free(lkp_key); ++ return NSS_STATUS_SUCCESS; ++ } ++ free(match); ++ } ++ free(lkp_key); ++ ++ return ret; ++} ++ ++int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) ++{ ++ struct lookup_context *ctxt = (struct lookup_context *) context; ++ struct map_source *source; ++ struct mapent_cache *mc; ++ char *mapent = NULL; ++ struct mapent *me; ++ int ret = 1; ++ ++ source = ap->entry->current; ++ ap->entry->current = NULL; ++ master_source_current_signal(ap->entry); ++ ++ mc = source->mc; ++ ++ /* Check if we recorded a mount fail for this key anywhere */ ++ me = lookup_source_mapent(ap, name, LKP_DISTINCT); ++ if (me) { ++ if (me->status >= time(NULL)) { ++ cache_unlock(me->mc); ++ return NSS_STATUS_NOTFOUND; ++ } else { ++ struct mapent_cache *smc = me->mc; ++ struct mapent *sme; ++ ++ if (me->mapent) ++ cache_unlock(smc); ++ else { ++ cache_unlock(smc); ++ cache_writelock(smc); ++ sme = cache_lookup_distinct(smc, name); ++ /* Negative timeout expired for non-existent entry. */ ++ if (sme && !sme->mapent) { ++ if (cache_pop_mapent(sme) == CHE_FAIL) ++ cache_delete(smc, name); ++ } ++ cache_unlock(smc); ++ } ++ } ++ } ++ ++ /* Catch installed direct offset triggers */ ++ cache_readlock(mc); ++ me = cache_lookup_distinct(mc, name); ++ if (!me) { ++ cache_unlock(mc); ++ /* ++ * If there's a '/' in the name and the offset is not in ++ * the cache then it's not a valid path in the mount tree. ++ */ ++ if (strchr(name, '/')) { ++ debug(ap->logopt, ++ MODPREFIX "offset %s not found", name); ++ return NSS_STATUS_NOTFOUND; ++ } ++ } else { ++ /* Otherwise we found a valid offset so try mount it */ ++ debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent); ++ ++ /* ++ * If this is a request for an offset mount (whose entry ++ * must be present in the cache to be valid) or the entry ++ * is newer than the negative timeout value then just ++ * try and mount it. Otherwise try and remove it and ++ * proceed with the program map lookup. ++ */ ++ if (strchr(name, '/') || ++ me->age + ap->negative_timeout > time(NULL)) { ++ char *ent = NULL; ++ ++ if (me->mapent) { ++ ent = alloca(strlen(me->mapent) + 1); ++ strcpy(ent, me->mapent); ++ } ++ cache_unlock(mc); ++ master_source_current_wait(ap->entry); ++ ap->entry->current = source; ++ ret = ctxt->parse->parse_mount(ap, name, ++ name_len, ent, ctxt->parse->context); ++ goto out_free; ++ } else { ++ if (me->multi) { ++ cache_unlock(mc); ++ warn(ap->logopt, MODPREFIX ++ "unexpected lookup for active multi-mount" ++ " key %s, returning fail", name); ++ return NSS_STATUS_UNAVAIL; ++ } ++ cache_unlock(mc); ++ cache_writelock(mc); ++ me = cache_lookup_distinct(mc, name); ++ if (me) ++ cache_delete(mc, name); ++ cache_unlock(mc); ++ } ++ } ++ ++ debug(ap->logopt, MODPREFIX "looking up %s", name); ++ ++ ret = match_key(ap, source, name, name_len, &mapent, ctxt); ++ if (ret != NSS_STATUS_SUCCESS) ++ goto out_free; + + debug(ap->logopt, MODPREFIX "%s -> %s", name, mapent); + diff --git a/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-yp-to-handle-amd-keys.patch b/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-yp-to-handle-amd-keys.patch new file mode 100644 index 0000000..5c9fd3b --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-update-lookup-yp-to-handle-amd-keys.patch @@ -0,0 +1,388 @@ +autofs-5.0.9 - amd lookup update lookup yp to handle amd keys + +From: Ian Kent + + +--- + modules/lookup_yp.c | 248 ++++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 216 insertions(+), 32 deletions(-) + +diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c +index ba97ccc..146e39e 100644 +--- a/modules/lookup_yp.c ++++ b/modules/lookup_yp.c +@@ -36,9 +36,10 @@ + #define MODPREFIX "lookup(yp): " + + struct lookup_context { +- const char *domainname; ++ char *domainname; + const char *mapname; + unsigned long order; ++ unsigned int check_defaults; + struct parse_mod *parse; + }; + +@@ -113,7 +114,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt = malloc(sizeof(struct lookup_context)); + if (!ctxt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- logerr(MODPREFIX "%s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return 1; + } + memset(ctxt, 0, sizeof(struct lookup_context)); +@@ -124,17 +125,28 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + return 1; + } + ctxt->mapname = argv[0]; +- +- /* This should, but doesn't, take a const char ** */ +- err = yp_get_default_domain((char **) &ctxt->domainname); +- if (err) { +- size_t len = strlen(ctxt->mapname); +- char *name = alloca(len + 1); +- memcpy(name, ctxt->mapname, len); +- name[len] = '\0'; +- free(ctxt); +- logerr(MODPREFIX "map %s: %s", name, yperr_string(err)); +- return 1; ++ ctxt->check_defaults = 1; ++ ++ if (mapfmt && !strcmp(mapfmt, "amd")) ++ ctxt->domainname = conf_amd_get_nis_domain(); ++ ++ if (!ctxt->domainname) { ++ char *domainname; ++ /* This should, but doesn't, take a const char ** */ ++ err = yp_get_default_domain(&domainname); ++ if (err) { ++ logerr(MODPREFIX ++ "map %s: %s", ctxt->mapname, yperr_string(err)); ++ free(ctxt); ++ return 1; ++ } ++ ctxt->domainname = strdup(domainname); ++ if (!ctxt->domainname) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ logerr(MODPREFIX "strdup: %s", estr); ++ free(ctxt); ++ return 1; ++ } + } + + ctxt->order = get_map_order(ctxt->domainname, ctxt->mapname); +@@ -286,7 +298,12 @@ int yp_all_callback(int status, char *ypkey, int ypkeylen, + if (*ypkey == '+') + return 0; + +- key = sanitize_path(ypkey, ypkeylen, ap->type, ap->logopt); ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) ++ key = sanitize_path(ypkey, ypkeylen, ap->type, ap->logopt); ++ else ++ /* Don't fail on "/" in key => type == 0 */ ++ key = sanitize_path(ypkey, ypkeylen, 0, ap->logopt); ++ + if (!key) { + error(logopt, MODPREFIX "invalid path %s", ypkey); + return 0; +@@ -372,6 +389,9 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + } + + source->age = age; ++ pthread_mutex_lock(&ap->entry->current_mutex); ++ ctxt->check_defaults = 0; ++ pthread_mutex_unlock(&ap->entry->current_mutex); + + return NSS_STATUS_SUCCESS; + } +@@ -432,6 +452,66 @@ static int lookup_one(struct autofs_point *ap, + return ret; + } + ++static int match_key(struct autofs_point *ap, ++ struct map_source *source, ++ const char *key, int key_len, ++ struct lookup_context *ctxt) ++{ ++ char buf[MAX_ERR_BUF]; ++ char *lkp_key; ++ char *prefix; ++ int ret; ++ ++ ret = lookup_one(ap, source, key, strlen(key), ctxt); ++ if (ret < 0) ++ return ret; ++ if (ret == CHE_OK || ret == CHE_UPDATED) ++ return ret; ++ ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) ++ return CHE_FAIL; ++ ++ lkp_key = strdup(key); ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "strdup: %s", estr); ++ return CHE_FAIL; ++ } ++ ++ ret = CHE_MISSING; ++ ++ /* ++ * Now strip successive directory components and try a ++ * match against map entries ending with a wildcard and ++ * finally try the wilcard entry itself. ++ */ ++ while ((prefix = strrchr(lkp_key, '/'))) { ++ char *match; ++ size_t len; ++ *prefix = '\0'; ++ len = strlen(lkp_key) + 3; ++ match = malloc(len); ++ if (!match) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ ret = CHE_FAIL; ++ goto done; ++ } ++ len--; ++ strcpy(match, lkp_key); ++ strcat(match, "/*"); ++ ret = lookup_one(ap, source, match, len, ctxt); ++ free(match); ++ if (ret < 0) ++ goto done; ++ if (ret == CHE_OK || ret == CHE_UPDATED) ++ goto done; ++ } ++done: ++ free(lkp_key); ++ return ret; ++} ++ + static int lookup_wild(struct autofs_point *ap, + struct map_source *source, struct lookup_context *ctxt) + { +@@ -480,6 +560,52 @@ static int lookup_wild(struct autofs_point *ap, + return ret; + } + ++static int lookup_amd_defaults(struct autofs_point *ap, ++ struct map_source *source, ++ struct lookup_context *ctxt) ++{ ++ struct mapent_cache *mc = source->mc; ++ char *mapname; ++ char *mapent; ++ int mapent_len; ++ int ret; ++ ++ mapname = malloc(strlen(ctxt->mapname) + 1); ++ if (!mapname) ++ return 0; ++ ++ strcpy(mapname, ctxt->mapname); ++ ++ ret = yp_match((char *) ctxt->domainname, mapname, ++ (char *) "/defaults", 9, &mapent, &mapent_len); ++ ++ if (ret != YPERR_SUCCESS) { ++ if (ret == YPERR_MAP) { ++ char *usc; ++ ++ while ((usc = strchr(mapname, '_'))) ++ *usc = '.'; ++ ++ ret = yp_match((char *) ctxt->domainname, mapname, ++ "/defaults", 9, &mapent, &mapent_len); ++ } ++ } ++ free(mapname); ++ ++ /* No /defaults entry */ ++ if (ret == YPERR_KEY) ++ return CHE_OK; ++ ++ if (ret != YPERR_SUCCESS) ++ return CHE_FAIL; ++ ++ cache_writelock(mc); ++ ret = cache_update(mc, source, "/defaults", mapent, time(NULL)); ++ cache_unlock(mc); ++ ++ return ret; ++} ++ + static int check_map_indirect(struct autofs_point *ap, + struct map_source *source, + char *key, int key_len, +@@ -492,8 +618,28 @@ static int check_map_indirect(struct autofs_point *ap, + + mc = source->mc; + ++ /* Only read map if it has been modified */ ++ pthread_mutex_lock(&ap->entry->current_mutex); ++ map_order = get_map_order(ctxt->domainname, ctxt->mapname); ++ if (map_order > ctxt->order) { ++ ctxt->order = map_order; ++ source->stale = 1; ++ ctxt->check_defaults = 1; ++ } ++ ++ if (source->flags & MAP_FLAG_FORMAT_AMD && ctxt->check_defaults) { ++ /* Check for a /defaults entry to update the map source */ ++ if (lookup_amd_defaults(ap, source, ctxt) == CHE_FAIL) { ++ warn(ap->logopt, MODPREFIX ++ "error getting /defaults from map %s", ++ ctxt->mapname); ++ } else ++ ctxt->check_defaults = 0; ++ } ++ pthread_mutex_unlock(&ap->entry->current_mutex); ++ + /* check map and if change is detected re-read map */ +- ret = lookup_one(ap, source, key, key_len, ctxt); ++ ret = match_key(ap, source, key, key_len, ctxt); + if (ret == CHE_FAIL) + return NSS_STATUS_NOTFOUND; + +@@ -503,7 +649,10 @@ static int check_map_indirect(struct autofs_point *ap, + * and belongs to this map return success and use the entry. + */ + cache_readlock(mc); +- exists = cache_lookup(mc, key); ++ if (source->flags & MAP_FLAG_FORMAT_AMD) ++ exists = match_cached_key(ap, MODPREFIX, source, key); ++ else ++ exists = cache_lookup(mc, key); + if (exists && exists->source == source) { + cache_unlock(mc); + return NSS_STATUS_SUCCESS; +@@ -517,15 +666,11 @@ static int check_map_indirect(struct autofs_point *ap, + return NSS_STATUS_UNAVAIL; + } + +- /* Only read map if it has been modified */ +- map_order = get_map_order(ctxt->domainname, ctxt->mapname); +- if (map_order > ctxt->order) { +- ctxt->order = map_order; +- source->stale = 1; +- } +- + cache_writelock(mc); +- exists = cache_lookup_distinct(mc, key); ++ if (source->flags & MAP_FLAG_FORMAT_AMD) ++ exists = match_cached_key(ap, MODPREFIX, source, key); ++ else ++ exists = cache_lookup_distinct(mc, key); + /* Not found in the map but found in the cache */ + if (exists && exists->source == source && ret & CHE_MISSING) { + if (exists->mapent) { +@@ -578,9 +723,11 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + struct mapent_cache *mc; + char key[KEY_MAX_LEN + 1]; + int key_len; ++ char *lkp_key; + char *mapent = NULL; + int mapent_len; + struct mapent *me; ++ char buf[MAX_ERR_BUF]; + int status = 0; + int ret = 1; + +@@ -592,9 +739,18 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + + debug(ap->logopt, MODPREFIX "looking up %s", name); + +- key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); +- if (key_len > KEY_MAX_LEN) +- return NSS_STATUS_NOTFOUND; ++ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { ++ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); ++ if (key_len > KEY_MAX_LEN) ++ return NSS_STATUS_NOTFOUND; ++ } else { ++ key_len = expandamdent(name, NULL, NULL); ++ if (key_len > KEY_MAX_LEN) ++ return NSS_STATUS_NOTFOUND; ++ memset(key, 0, KEY_MAX_LEN + 1); ++ expandamdent(name, key, NULL); ++ debug(ap->logopt, MODPREFIX "expanded key: \"%s\"", key); ++ } + + /* Check if we recorded a mount fail for this key anywhere */ + me = lookup_source_mapent(ap, key, LKP_DISTINCT); +@@ -628,18 +784,26 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + * we never know about it. + */ + if (ap->type == LKP_INDIRECT && *key != '/') { +- char *lkp_key; +- + cache_readlock(mc); + me = cache_lookup_distinct(mc, key); + if (me && me->multi) + lkp_key = strdup(me->multi->key); +- else ++ else if (!ap->pref) + lkp_key = strdup(key); ++ else { ++ lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1); ++ if (lkp_key) { ++ strcpy(lkp_key, ap->pref); ++ strcat(lkp_key, key); ++ } ++ } + cache_unlock(mc); + +- if (!lkp_key) ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); + return NSS_STATUS_UNKNOWN; ++ } + + status = check_map_indirect(ap, source, + lkp_key, strlen(lkp_key), ctxt); +@@ -660,7 +824,25 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + cache_readlock(mc); + else + cache_writelock(mc); +- me = cache_lookup(mc, key); ++ ++ if (!ap->pref) ++ lkp_key = strdup(key); ++ else { ++ lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1); ++ if (lkp_key) { ++ strcpy(lkp_key, ap->pref); ++ strcat(lkp_key, key); ++ } ++ } ++ ++ if (!lkp_key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ cache_unlock(mc); ++ return NSS_STATUS_UNKNOWN; ++ } ++ ++ me = match_cached_key(ap, MODPREFIX, source, lkp_key); + /* Stale mapent => check for entry in alternate source or wildcard */ + if (me && !me->mapent) { + while ((me = cache_lookup_key_next(me))) +@@ -687,6 +869,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + } + } + cache_unlock(mc); ++ free(lkp_key); + + if (mapent) { + master_source_current_wait(ap->entry); +@@ -716,6 +899,7 @@ int lookup_done(void *context) + { + struct lookup_context *ctxt = (struct lookup_context *) context; + int rv = close_parse(ctxt->parse); ++ free(ctxt->domainname); + free(ctxt); + return rv; + } diff --git a/SOURCES/autofs-5.0.9-amd-lookup-update-man-page-autofs-config-description.patch b/SOURCES/autofs-5.0.9-amd-lookup-update-man-page-autofs-config-description.patch new file mode 100644 index 0000000..5ec7125 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-update-man-page-autofs-config-description.patch @@ -0,0 +1,74 @@ +autofs-5.0.9 - update man page autofs config description + +From: Ian Kent + + +--- + man/auto.master.5.in | 43 ++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 38 insertions(+), 5 deletions(-) + +diff --git a/man/auto.master.5.in b/man/auto.master.5.in +index eb31c93..59df04f 100644 +--- a/man/auto.master.5.in ++++ b/man/auto.master.5.in +@@ -205,14 +205,47 @@ or in the configuration. + Set the timeout for caching failed key lookups. This option can be + used to override the global default given either on the command line + or in the configuration. +-.SH GENERAL SYSTEM DEFAULTS CONFIGURATION ++.SH AUTOFS CONFIGURATION + .P +-The default value of several general settings may be changed in the +-configuration file ++There are two files that amy contain configuration settings + .nh ++.BR @@autofsmapdir@@/autofs.conf . ++.hy ++and + .BR @@autofsconfdir@@/autofs . + .hy +-They are: ++The former contains the bulk of configuration options while the later ++contains entries to be set in the environment for use by the init ++sub-system. ++.TP ++The only entry currently present in the init system configuration ++is OPTIONS which may be used to specify options to be used when ++starting ++.BR automount (8) . ++.TP ++Previously all configuration entries were located in the init system ++configuration file and their values were set in the environment for ++later use by autofs. Configuration entries that were set in the ++environment continue to be set in the environment at program startup ++and any setting already present in the environment takes precedence. ++.SH SYSTEM DEFAULTS CONFIGURATION ++.P ++The value of most settings may be set in the configuration file ++.nh ++.BR @@autofsmapdir@@/autofs.conf . ++.hy ++Configuration entries are "name = value" pairs and the name is case ++insensitive. Older configuration names had a DEFAULTS_ prefix which ++is appended to the configuration name when a value isn't found and ++the search repeated. ++.TP ++An optional section name ++.nh ++.BR [ autofs ] ++.hy ++may also be given. ++.TP ++The available configuration entries are: + .TP + .B timeout + Sets the default mount timeout in seconds. The internal program +@@ -308,7 +341,7 @@ The object classes and attributes used for accessing automount maps in + LDAP can be changed by setting entries in the autofs configuration + located in + .nh +-.BR @@autofsconfdir@@/autofs . ++.BR @@autofsmapdir@@/autofs.conf . + .hy + .TP + .B NOTE: diff --git a/SOURCES/autofs-5.0.9-amd-lookup-update-man-pages.patch b/SOURCES/autofs-5.0.9-amd-lookup-update-man-pages.patch new file mode 100644 index 0000000..4b8072e --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-update-man-pages.patch @@ -0,0 +1,1085 @@ +autofs-5.0.9 - amd lookup update man pages + +From: Ian Kent + +Update man pages to reflect the addition of the amd map format +parser, move configuration to it's own man page and update with +amd options descriptions. +--- + man/auto.master.5.in | 183 ++---------------- + man/autofs.5 | 346 +++++++++++++++++++++++++++++++++- + man/autofs.8.in | 1 + man/autofs.conf.5.in | 412 ++++++++++++++++++++++++++++++++++++++++ + man/autofs_ldap_auth.conf.5.in | 1 + man/automount.8 | 1 + 6 files changed, 782 insertions(+), 162 deletions(-) + create mode 100644 man/autofs.conf.5.in + +diff --git a/man/auto.master.5.in b/man/auto.master.5.in +index 59df04f..2267550 100644 +--- a/man/auto.master.5.in ++++ b/man/auto.master.5.in +@@ -122,14 +122,18 @@ will be ignored if its name is not ended with the suffix. In addition a dot file + which name is started with "." is also ignored. + .RE + .TP +-\fBformat\fP +-Format of the map data; currently the only formats +-recognized are \fBsun\fP, which is a subset of the Sun automounter map +-format, and \fBhesiod\fP, for hesiod filesys entries. If the format is +-left unspecified, it defaults to \fBsun\fP for all map types except +-\fBhesiod\fP. +-.TP +-\fBmap\fP ++.B format ++.br ++Format of the map data; currently the formats recognized are \fBsun\fP, ++which is a subset of the Sun automounter map format, \fBhesiod\fP, for ++hesiod filesys entries and \fBamd\fP for amd formated map entries. ++If the format is left unspecified, it defaults to \fBsun\fP for all map ++types except \fBhesiod\fP unless it is a top level \fBamd\fP mount that ++has a configuration entry for the mount point path, in which case the ++format used is \fBamd\fP. ++.TP ++.B map ++.br + Name of the map to use. This is an absolute UNIX pathname + for maps of types \fBfile\fP, \fBdir\fP, or \fBprogram\fP, and the name of a database + in the case for maps of type \fByp\fP, \fBnisplus\fP, or \fBhesiod\fP or +@@ -205,87 +209,6 @@ or in the configuration. + Set the timeout for caching failed key lookups. This option can be + used to override the global default given either on the command line + or in the configuration. +-.SH AUTOFS CONFIGURATION +-.P +-There are two files that amy contain configuration settings +-.nh +-.BR @@autofsmapdir@@/autofs.conf . +-.hy +-and +-.BR @@autofsconfdir@@/autofs . +-.hy +-The former contains the bulk of configuration options while the later +-contains entries to be set in the environment for use by the init +-sub-system. +-.TP +-The only entry currently present in the init system configuration +-is OPTIONS which may be used to specify options to be used when +-starting +-.BR automount (8) . +-.TP +-Previously all configuration entries were located in the init system +-configuration file and their values were set in the environment for +-later use by autofs. Configuration entries that were set in the +-environment continue to be set in the environment at program startup +-and any setting already present in the environment takes precedence. +-.SH SYSTEM DEFAULTS CONFIGURATION +-.P +-The value of most settings may be set in the configuration file +-.nh +-.BR @@autofsmapdir@@/autofs.conf . +-.hy +-Configuration entries are "name = value" pairs and the name is case +-insensitive. Older configuration names had a DEFAULTS_ prefix which +-is appended to the configuration name when a value isn't found and +-the search repeated. +-.TP +-An optional section name +-.nh +-.BR [ autofs ] +-.hy +-may also be given. +-.TP +-The available configuration entries are: +-.TP +-.B timeout +-Sets the default mount timeout in seconds. The internal program +-default is 10 minutes, but the default installed configuration +-overrides this and sets the timeout to 5 minutes to be consistent +-with earlier autofs releases. +-.TP +-.B negative_timeout +-Set the default timeout for caching failed key lookups (program default +-60). If the equivalent command line option is given it will override this +-setting. +-.TP +-.B mount_wait +-Set the default time to wait for a response from a spawned mount(8) +-before sending it a SIGTERM. Note that we still need to wait for the +-RPC layer to timeout before the sub-process exits so this isn't ideal +-but it is the best we can do. The default is to wait until mount(8) +-returns without intervention. +-.TP +-.B umount_wait +-Set the default time to wait for a response from a spawned umount(8) +-before sending it a SIGTERM. Note that we still need to wait for the +-RPC layer to timeout before the sub-process exits so this isn't ideal +-but it is the best we can do. +-.TP +-.B browse_mode +-Maps are browsable by default (program default "yes"). +-.TP +-.B mount_nfs_default_protocol +-Specify the default protocol used by mount.nfs(8) (program default 3). Since +-we can't identify this default automatically we need to set it in the autofs +-configuration. +-.TP +-.B append_options +-Determine whether global options, given on the command line or per mount +-in the master map, are appended to map entry options or if the map entry +-options replace the global options (program default "yes", append options). +-.TP +-.B logging +-set default log level "none", "verbose" or "debug" (program default "none"). + .SH BUILTIN MAP -hosts + If "-hosts" is given as the map then accessing a key under the mount point + which corresponds to a hostname will allow access to the exports of that +@@ -341,76 +264,21 @@ The object classes and attributes used for accessing automount maps in + LDAP can be changed by setting entries in the autofs configuration + located in + .nh +-.BR @@autofsmapdir@@/autofs.conf . ++.BR @@autofsconfdir@@/autofs.conf . + .hy + .TP + .B NOTE: + If a schema is given in the configuration then all the schema configuration + values must be set, any partial schema specification will be ignored. +-.P +-The configuration settings available are: +-.TP +-.B ldap_timeout +-Set the network response timeout (default 8). +-Set timeout value for the synchronous API calls. The default is the LDAP +-library default of an infinite timeout. + .TP +-.B ldap_network_timeout +-Set the network response timeout (default 8). +-.TP +-.B ldap_uri +-A space seperated list of server uris of the form ://[/] +-where can be ldap or ldaps. The option can be given multiple times. +-Map entries that include a server name override this option and it is then +-not used. Default is an empty list in which case either the server given +-in a map entry or the LDAP configured default is used. This uri list is read at +-startup and whenever the daemon receives a HUP signal. +-.P +-This configuration option can also be used to request autofs lookup SRV RRs +-for a domain of the form :///[]. Note that a trailing +-"/" is not allowed when using this form. If the domain dn is not specified +-the dns domain name (if any) is used to construct the domain dn for the +-SRV RR lookup. The server list returned from an SRV RR lookup is refreshed +-according to the minimum ttl found in the SRV RR records or after one hour, +-whichever is less. ++For \fBamd\fP format maps a different schema is used: + .TP +-.B search_base +-The base dn to use when searching for amap base dn. This entry may be +-given multiple times and each will be checked for a map base dn in +-the order they occur in the configuration. The search base list is read +-at startup and whenever the daemon recieves a HUP signal. +-.TP +-.B map_object_class +-The map object class. In the \fBnisMap\fP schema this corresponds to the class +-\fBnisMap\fP and in the \fBautomountMap\fP schema it corresponds to the class +-\fBautomountMap\fP. +-.TP +-.B entry_object_class +-The map entry object class. In the \fBnisMap\fP schema this corresponds +-to the class \fBnisObject\fP and in the \fBautomountMap\fP schema it +-corresponds to the class \fBautomount\fP. +-.TP +-.B map_attribute +-The attribute used to identify the name of the map to which this +-entry belongs. In the \fBnisMap\fP schema this corresponds to the attribute +-\fBnisMapName\fP and in the \fBautomountMap\fP schema it corresponds to the +-attribute \fBou\fP or \fBautomountMapName\fP. +-.TP +-.B entry_attribute +-The attribute used to identify a map key. In the \fBnisMap\fP schema this +-corresponds to the attribute \fBcn\fP and in the \fBautomountMap\fP schema +-it corresponds to the attribute \fBautomountKey\fP. +-.TP +-.B value_attribute +-The attribute used to identify the value of the map entry. In the \fBnisMap\fP +-schema this corresponds to the attribute \fBnisMapEntry\fP and in the \fBautomountMap\fP +-schema it corresponds to the attribute \fBautomountInformation\fP. +-.TP +-.B NOTE: +-It is essential that entries use class and attribute in a consistent +-manner for correct operation of autofs. For example mixing \fBcn\fP and +-\fBautomountKey\fP attributes in \fBautomount\fP schema map entries won't +-work as expected. ++.I amdMap ++.br ++The \fBamdmap\fP schema contains attributes \fBamdmapName\fP, \fBamdmapKey\fP ++and \fBamdmapValue\fP where \fBamdmapName\fP contains the name of the containing ++map, \fBamdmapKey\fP contains the map key and \fBamdmapValue\fP contains the ++map entry. + .SH LDAP AUTHENTICATION, ENCRYPTED AND CERTIFIED CONNECTIONS + LDAP authenticated binds, TLS encrypted connections and certification + may be used by setting appropriate values in the autofs authentication +@@ -419,10 +287,6 @@ settings. The default location of this file is + .nh + .BR @@autofsmapdir@@/autofs_ldap_auth.conf . + .hy +-.TP +-.B auth_conf_file +-This configuration option may be used to specify an alternate location +-for the ldap authentication file + .P + If this file exists it will be used to establish whether TLS or authentication + should be used. +@@ -458,7 +322,9 @@ in the per-user configuration. The location of these files and the configuration + entry requirements is system dependent so the documentation for your + installation will need to be consulted to get further information. + .P +-See \fBautofs_ldap_auth.conf\fP(5) for more information. ++See ++.B autofs_ldap_auth.conf (5) ++for more information. + .SH EXAMPLE + .sp + .RS +.2i +@@ -492,7 +358,8 @@ configuration will be used to locate the source of the map + .SH "SEE ALSO" + .BR automount (8), + .BR autofs (5), +-.BR autofs (8). ++.BR autofs (8), ++.BR autofs.conf (5), + .BR autofs_ldap_auth.conf (5) + .SH AUTHOR + This manual page was written by Christoph Lameter , +diff --git a/man/autofs.5 b/man/autofs.5 +index c3a1611..81ae375 100644 +--- a/man/autofs.5 ++++ b/man/autofs.5 +@@ -1,6 +1,5 @@ + .\" t +-.TH AUTOFS 5 "6 Apr 1998" +-.TH AUTOFS 5 "14 Jan 2000" ++.TH AUTOFS 5 "9 Feb 2014" + .SH NAME + autofs \- Format of the automounter maps + .SH "DESCRIPTION" +@@ -10,14 +9,16 @@ the master map of the automounter (see + These maps describe how file systems below the mount point of the map + (given in the master map) are to be mounted. This page describes the + .B sun +-map format; if another map format is specified (e.g. \fBhesiod\fP), ++map format; if another map format, other than ++.B amd , ++is specified (e.g. \fBhesiod\fP), + this documentation does not apply. + + Indirect maps, except for the internal hosts map, can be changed on the fly + and the automouter will recognize those changes on the next operation it + performs on that map. Direct maps require a HUP signal be sent to the + daemon to refresh their contents as does the master map. +-.SH "FORMAT" ++.SH "SUN FORMAT" + This is a description of the text file format. Other methods of specifying + these files may exist. All empty lines or lines beginning with # are + ignored. The basic format of one line in such maps is: +@@ -245,10 +246,347 @@ Anything else is questionable and unsupported, but these variations will also wo + .SH UNSUPPORTED + This version of the automounter supports direct maps stored in FILE, NIS, NISPLUS + and LDAP only. ++.P ++.SH "AMD FORMAT" ++This is a description of the text file format. Other methods of specifying ++mount map entries may be required for different map sources. All empty ++lines or lines beginning with # are ignored. The basic format of one ++line in such maps is: ++.P ++.BR key\ location-list ++.TP ++.B key ++.br ++A \fBkey\fP is a path (or a single path component alone) that may end ++in the wildcard key, "*", or the wildcard key alone and must not begin ++with the "/" character. ++.TP ++.B location-list ++Following the \fBkey\fP is a mount \fBlocation-list\fP. ++.TP ++A \fBlocation-list\fP list has the following syntax: ++.TP ++.B location[\ location[\ ...\ ]]\ [||\ location[\ location[\ ...\ ]] ++.P ++A mount \fBlocation-list\fP can use the cut operator, \fB||\fP, to specify ++locations that should be tried if none of the locations to the left of it ++where selected for a mount attempt. ++ ++A mount \fBlocation\fP consists of an optional colon seperated list ++of \fBselectors\fP, followed by a colon seperated list of \fBoption:=value\fP ++pairs. ++ ++The \fBselectors\fP that may be used return a value or boolean result. ++Those that return a value may be to used with the comparison ++operators \fB==\fP and \fB!=\fP and those that return a boolean result ++may be negated with the \fB!\fP. ++ ++For a \fBlocation\fP to be selected for a mount attempt all of its \fBselectors\fP ++must evaluate to true. If a \fBlocation\fP is selected for a mount attempt ++and succeeds the lookup is completed and returns success. If the mount ++attempt fails the proceedure continues with the next \fBlocation\fP until ++they have all been tried. ++ ++In addition some \fBselectors\fP take no argumenets, some one argument ++and others optionally take two arguments. ++ ++The \fBselectors\fP that take no arguments are: ++.RS ++.TP ++.B arch ++.br ++The machine architecture which, if not set in the confugration, is ++obtained using uname(2). ++.TP ++.B karch ++.br ++The machine kernel architecture which, if not set in the confugration, ++is obtained using uname(2). ++.TP ++.B os ++.br ++The operating system name, if not set in the confugration, is obtained ++using uname(2). ++.TP ++.B osver ++.br ++The operating system version, if not set in the confugration, is obtained ++using uname(2). ++.TP ++.B full_os ++.br ++The full operating system name, if not set in the confugration this selector ++has no value. ++.TP ++.B vendor ++.br ++The operating system vendor name, if not set in the confugration this selector ++has the value "unknown". ++.TP ++.B byte ++.br ++The endianess of the hardware. ++.TP ++.B cluster ++.br ++The name of the local cluster. It has a value only if it is set in the ++configuration. ++.TP ++.B autodir ++.br ++The base path under which external mounts are done if they are needed. ++Most mounts are done in place but some can't be and this is the base ++path under which those mounts will be done. ++.TP ++.B domain ++.br ++The local domain name. It is set to the value of the configuration ++option \fBsub_domain\fP. If sub_domain is not given in the configuration ++it is set to the domain part of the local host name, as given by ++gethostname(2). ++.TP ++.B host ++.br ++The local host name, without the domain part, as given by gethostname(2). ++.TP ++.B hostd ++.br ++The full host name. If \fBsub_domain\fP is given in the configuration ++this is set to the contatenation of \fBhost\fP and \fBsub_domain\fP deperated ++by a \fB.\fP. If \fBsub_domain\fP is not set in the configuration the value ++of \fBdomain\fP is used instead of \fBsub_domain\fP. ++.TP ++.B uid ++.br ++The numeric value of the uid of the user that first requested the mount. Note ++this is usual the same as that used by amd but can be different within autofs. ++.TP ++.B gid ++.br ++The numeric value of the gid of the user that first requested the mount. Note ++this is usual the same as that used by amd but can be different within autofs. ++.TP ++.B key ++.br ++The string value of the key being looked up. ++.TP ++.B map ++.br ++The string value of the map name used to lookup \fBkey\fPs. ++.TP ++.B path ++.br ++The string value of the full path to the mount being requested. ++.TP ++.B dollar ++.br ++Evaluates to the string "$". ++.RE ++.TP ++The \fBselectors\fP that take one argument are: ++.RS ++.TP ++.B in_network(network) ", " network(network) ", " netnumber(network) ", " wire(network) ++.br ++These \fBselectors\fP are all the same. \fBin_network()\fP is the ++preferred usage. The \fBnetwork\fP argument is an address (which may include ++a subnet mask) or network name. The function compares \fBnetwork\fP ++against each interface and returns true if \fBnetwork\fP belongs to ++the network the interface is connected to. ++.TP ++.B xhost(hostname) ++.br ++The \fBxhost()\fP selector compares \fBhostname\fP to the \fB${host}\fP ++and if it doesn't match it attempts to lookup the cannonical name ++of \fBhostname\fP and compares it to \f${host}\fP as well. ++.TP ++.B exists(filename) ++.br ++Returns true if \fBfilename\fP exits as determined by lstat(2). ++.TP ++.B true() ++.br ++Evaluates to true, the argument is ignored and may be empty. ++.TP ++.B false() ++.br ++Evaluates to false, the argument is ignored and may be empty. ++.RE ++.TP ++The \fBselectors\fP that take up to two arguments are: ++.RS ++.TP ++.B netgrp(netgroup[,hostname]) ++.br ++The \fBnetgrp()\fP selector returns true if \fPhostname\fP is a member of ++the netgroup \fBnetgroup\fP. If \fBhostname\fP is not given \fB${host}\fP ++is used for the comparison. ++.TP ++.B netgrpd(netgroup[,hostname]) ++.br ++The \fBnetgrpd()i\fP selector behaves the same as \fBnetgrp()\fP except ++that if \fBhostname\fP is not given \fB${hostd}\fP, the fully qualified ++hostname, is used instead of \fB${host}\fP. ++.RE ++.TP ++The \fBoptions\fP that may be used are: ++.RS ++.TP ++.B type ++.br ++This is the mount filesystem \fBtype\fP. ++It can have a value of ++.BR auto ", " link ", " linkx ", " host ", " lofs ", " ext2-4 ", " ++.BR xfs ", " nfs ", " nfsl " or " cdfs "." ++Other types that are not yet implemented or are not available iin autofs are ++.BR nfsx ", " lustre ", " jfs ", " program ", " cachefs " and " direct "." ++.TP ++.B maptype ++.br ++The \fBmaptype\fP option specifies the type of the map source and can ++have a value of \fBfile\fP, \fBnis\fP, \fBnisplus\fP, \fBexec\fP, \fBldap\fP ++or \fBhesiod\fP. Map sources either not yet implemented or not available in ++autofs are \fBsss\fP, \fBndbm\fP, \fBpasswd\fP and \fBunion\fP. ++.TP ++.B fs ++.br ++The option \fBfs\fP is used to specify the local filesystem. The meaning of ++this option (and whether or not it is used) is dependent on the mount ++filesystem \fBtype\fP. ++.TP ++.B rhost ++.br ++The remote host name for network mount requests. ++.TP ++.B rfs ++.br ++The remote host filesystem path for network mount requests. ++.TP ++.B dev ++.br ++Must resolve to the device file for local device mount ++requests. ++.TP ++.B sublink ++.br ++The \fBsublink\fP option is used to specify a subdirectory ++within the mount location to which this entry will point. ++.TP ++.B pref ++.br ++The \fBpref\fP option is used to specify a prefix that is ++prepended to the lookup key before looking up the map entry ++key. ++.TP ++.B opts ++.br ++The \fBopts\fP option is used to specify mount options to be ++used for the mount. If a "\fB-\fP" is given it is ignored. ++Options that may be used are dependend on the mount filesystem. ++.TP ++.B addopts ++.br ++The \fBaddopts\fP option is used to specify additional mount ++options used in addition to the default mount options for the ++mount location. ++.TP ++.B remopts ++.br ++The \fBaddopts\fP option is used to specify mount options used ++instead the options given in \fBopts\fP when the mount location ++is on a remote retwork. ++.RE ++.TP ++A number of \fBoptions\fP aren't available or aren't yet implemented ++within autofs, these are: ++.RS ++.TP ++.B cache ++.br ++The \fBcache option\fP isn't used by autofs. The map entry cache is ++continually updated and stale entries cleaned on re-load when map ++changes are detected so these configuration entries are not used. ++The \fBregex\fP map key matching is not implemented and may not be ++due to the potential overhead of the full map scans needed on every ++key lookup. ++.TP ++.B cachedir ++.br ++The \fBcachefs\fP filesystem is not available on Linux, a different ++implementation is used for caching network mounted file systems. ++.TP ++.B mount ", " unmount ", " umount ++.br ++These \fBoptions\fP are used by the amd \fBprogram\fP mount type which ++is not yet implemented. ++.TP ++.B delay ++.br ++This \fBoption\fP is not used by the autofs implementation and is ignored. ++.RE ++.BR ++.SH FEATURES ++.SS Key Matching ++The amd parser key matching is unusual. ++ ++The key string to be looked up is constructed by prepending the prefix, if ++there is one. ++ ++The resulting relative path string is matched by first trying the sting ++itself. If no match is found the last component of the key string is ++replaced with the wilcard match cahracter ("*") and a wildcard match is ++attemted. This process continues until a match is found or until the ++last match, against the wilcard match key alone, fails to match a map ++entry and the key lookup fails. ++.SS Macro Usage ++Macros are used a lot in the autofs amd implementation. ++ ++Many of the option values are set as macro variables corresponding to the ++option name during the map entry parse. So they may be used in subsequent ++option values. Beware though, the order in which option values is not ++necessarily left to right so you may get unexpected results. ++.BR ++.SH EXAMPLE ++Example NFS mount map: ++.P ++Assuming we have the autofs master map entry: ++.sp ++.RS +.2i ++.ta 1.0i 3.0i ++.nf ++/test file,amd:/etc/amd.test ++.fi ++.RE ++.sp ++And the following map in /etc/amd.test: ++.sp ++.RS +.2i ++.ta 1.0i 3.0i ++.nf ++/defaults type:=nfs;rhost:=bilbo ++apps rfs:=/autofs ++util rhost:=zeus;rfs:=/work/util ++local rfs:=/shared;sublink:=local ++.fi ++.RE ++.sp ++In the first line we have an NFS remote mount of the exported directory ++/autofs from host bilbo which would be mounted on /test/apps. Next ++another nfs mount for the exported directory /work/util from host zeus. ++This would be mounted on /test/util. ++ ++Finally we have an example of the use of the \fBsublink\fP option. In ++this case the filesystem bilbo:/shared would be mounted on a path ++external the automount directory (under the direcory given by ++configuration option auto_dir) and the path /test/local either ++symlinked or bind mounted (depending on the setting autofs_use_lofs) ++to the "local" subdirectory of the external mount. ++.BR + .SH "SEE ALSO" + .BR automount (8), + .BR auto.master (5), + .BR autofs (8), ++.BR autofs.conf (5), + .BR mount (8). + .BR autofs_ldap_auth.conf (5) + .SH AUTHOR +diff --git a/man/autofs.8.in b/man/autofs.8.in +index fae0b00..7ab4242 100644 +--- a/man/autofs.8.in ++++ b/man/autofs.8.in +@@ -49,6 +49,7 @@ will display the status of, + .SH "SEE ALSO" + .BR automount (8), + .BR autofs (5), ++.BR autofs.conf (5), + .BR auto.master (5). + .BR autofs_ldap_auth.conf (5) + .SH AUTHOR +diff --git a/man/autofs.conf.5.in b/man/autofs.conf.5.in +new file mode 100644 +index 0000000..aad4143 +--- /dev/null ++++ b/man/autofs.conf.5.in +@@ -0,0 +1,412 @@ ++.\" t ++.TH AUTOFS.CONF "23 Jan 2014" ++.SH NAME ++autofs.conf \- autofs configuration ++.SH "DESCRIPTION" ++.P ++Configuration settings used by ++.BR automount (8) ++may be changed in the configuration file \fB@@autofsmapdir@@/autofs.conf\fP. ++.P ++This file contains two primary sections, \fBautofs\fP and \fBamd\fP. ++.P ++Configuration entries may be present at the beginning of the ++configuration file without a section header and are implicitly ++included as part of the \fBautofs\fP section. ++.P ++Each section name is enclosed in square brackets with ++spaces between the brackets and the section name. The \fBamd\fP ++section may be followed by further sections, named by the ++top level mount point path, that contain per mount ++configuration settings. ++.SH "SECTION autofs CONFIGURATION OPTIONS" ++.P ++Configuration settings available are: ++.TP ++.B timeout ++.br ++Sets the default mount timeout in seconds. The internal program ++default is 10 minutes, but the default installed configuration ++overrides this and sets the timeout to 5 minutes to be consistent ++with earlier autofs releases. ++.TP ++.B negative_timeout ++.br ++Set the default timeout for caching failed key lookups (program default ++60). If the equivalent command line option is given it will override this ++setting. ++.TP ++.B mount_wait ++.br ++Set the default time to wait for a response from a spawned mount(8) ++before sending it a SIGTERM. Note that we still need to wait for the ++RPC layer to timeout before the sub-process exits so this isn't ideal ++but it is the best we can do. The default is to wait until mount(8) ++returns without intervention. ++.TP ++.B umount_wait ++.br ++Set the default time to wait for a response from a spawned umount(8) ++before sending it a SIGTERM. Note that we still need to wait for the ++RPC layer to timeout before the sub-process exits so this isn't ideal ++but it is the best we can do. ++.TP ++.B browse_mode ++.br ++Maps are browsable by default (program default "yes"). ++.TP ++.B mount_nfs_default_protocol ++.br ++Specify the default protocol used by ++.BR mount.nfs (8) ++(program default 3). Since we can't identify this default automatically ++we need to set it in the autofs configuration. ++.TP ++.B append_options ++.br ++Determine whether global options, given on the command line or per mount ++in the master map, are appended to map entry options or if the map entry ++options replace the global options (program default "yes", append options). ++.TP ++.B logging ++.br ++set default log level "none", "verbose" or "debug" (program default "none"). ++.SS LDAP Configuration ++.P ++Configuration settings available are: ++.TP ++.B ldap_timeout ++.br ++Set the network response timeout (default 8). ++Set timeout value for the synchronous API calls. The default is the LDAP ++library default of an infinite timeout. ++.TP ++.B ldap_network_timeout ++.br ++Set the network response timeout (default 8). ++.TP ++.B ldap_uri ++.br ++A space seperated list of server uris of the form ://[/] ++where can be ldap or ldaps. The option can be given multiple times. ++Map entries that include a server name override this option and it is then ++not used. Default is an empty list in which case either the server given ++in a map entry or the LDAP configured default is used. This uri list is read at ++startup and whenever the daemon receives a HUP signal. ++ ++This configuration option can also be used to request autofs lookup SRV RRs ++for a domain of the form :///[]. Note that a trailing ++"/" is not allowed when using this form. If the domain dn is not specified ++the dns domain name (if any) is used to construct the domain dn for the ++SRV RR lookup. The server list returned from an SRV RR lookup is refreshed ++according to the minimum ttl found in the SRV RR records or after one hour, ++whichever is less. ++.TP ++.B search_base ++.br ++The base dn to use when searching for amap base dn. This entry may be ++given multiple times and each will be checked for a map base dn in ++the order they occur in the configuration. The search base list is read ++at startup and whenever the daemon recieves a HUP signal. ++.TP ++.B map_object_class ++.br ++The map object class. In the \fBnisMap\fP schema this corresponds to the class ++\fBnisMap\fP and in the \fBautomountMap\fP schema it corresponds to the class ++\fBautomountMap\fP. ++.TP ++.B entry_object_class ++.br ++The map entry object class. In the \fBnisMap\fP schema this corresponds ++to the class \fBnisObject\fP and in the \fBautomountMap\fP schema it ++corresponds to the class \fBautomount\fP. ++.TP ++.B map_attribute ++.br ++The attribute used to identify the name of the map to which this ++entry belongs. In the \fBnisMap\fP schema this corresponds to the attribute ++\fBnisMapName\fP and in the \fBautomountMap\fP schema it corresponds to the ++attribute \fBou\fP or \fBautomountMapName\fP. ++.TP ++.B entry_attribute ++.br ++The attribute used to identify a map key. In the \fBnisMap\fP schema this ++corresponds to the attribute \fBcn\fP and in the \fBautomountMap\fP schema ++it corresponds to the attribute \fBautomountKey\fP. ++.TP ++.B value_attribute ++.br ++The attribute used to identify the value of the map entry. In the \fBnisMap\fP ++schema this corresponds to the attribute \fBnisMapEntry\fP and in the \fBautomountMap\fP ++schema it corresponds to the attribute ++.BR automountInformation . ++.TP ++.B NOTE: ++It is essential that entries use class and attribute in a consistent ++manner for correct operation of autofs. For example mixing \fBcn\fP ++and \fBautomountKey\fP attributes in \fBautomount\fP schema will ++not work as expected. ++.TP ++.B auth_conf_file ++This configuration option may be used to specify an alternate location ++for the ldap authentication configuration file. See ++.BR autofs_ldap_auth.conf (5) ++for more information. ++.SH "SECTION amd CONFIGURATION OPTIONS" ++.P ++A number of the amd configuration options are not used by autofs, ++some because they are not relevant within autofs, some because ++they are done differently in autofs and others that are not yet ++implemented. ++ ++Since \fBmount_type\fP is always autofs (because there's no user space ++NFS server) the configuration entries relating to that aren't used. ++Also, server availability is done differently within autofs so the ++options that relate to the amd server monitoring sub-system are ++also not used. ++ ++These options are \fBmount_type\fP, \fBauto_attrcache\fP, \fBportmap_program\fP, ++\fBnfs_vers_ping\fP, \fBnfs_allow_any_interface\fP, \fBnfs_allow_insecure_port\fP, ++\fBnfs_proto\fP, \fBnfs_retransmit_counter\fP, \fBnfs_retransmit_counter_udp\fP, ++\fBnfs_retransmit_counter_tcp\fP, \fBnfs_retransmit_counter_toplvl\fP, ++\fBnfs_retry_interval\fP, \fBnfs_retry_interval_udp\fP, \fBnfs_retry_interval_tcp\fP, ++\fBnfs_retry_interval_toplvl\fP and \fBnfs_vers\fP. ++ ++Other options that are not used within the autofs implementation: ++.TP ++.BR log_file ", " truncate_log ++.br autofs used either stderr when running in the foreground or ++sends its output to syslog so an alternate log file (or truncating ++the log) can't be used. ++.TP ++.B print_pid ++.br ++There's no corresponding option for this within autofs. ++.TP ++.BR use_tcpwrappers ", " show_statfs_entries ++.br ++There's no user space NFS server to control access to so this ++option isn't relevant. The show_statfs_entries can't be ++implemented for the same reason. ++.TP ++.B debug_mtab_file ++.br ++There's no user space NFS server and autofs avoids using file ++based mtab whenever possible. ++.TP ++.B sun_map_syntax ++.br ++Sun map format is handled by autofs itself. ++.TP ++.BR plock ", " show_statfs_entries ", " preferred_amq_port ++.br ++Are not supported by autofs. ++.TP ++.BR ldap_cache_maxmem ", " ldap_cache_seconds ++.br ++External ldap caching is not used by autofs. ++.TP ++.B ldap_proto_version ++.br ++autofs always attempts to use the highest available ldap ++protocol version. ++.TP ++.BR cache_duration ", " map_reload_interval ", " map_options ++.br ++The map entry cache is continually updated and stale entries ++cleaned on re-load, which is done when map changes aredetected ++so these configuration entries are not used by autofs. ++.TP ++.B localhost_address ++This is not used within autofs. This configuration option was ++only used in the amd user space server code and is not relevant ++within autofs. ++.P ++Options that are handled differently within autofs: ++.TP ++.B pid_file ++.br ++To specify a pid file name a command line option must be used on startup. ++.TP ++.B print_version ++.br ++Program version and feature information is obtained by using the ++automount command line option "-V". ++.TP ++.B debug_options ", " log_options ++.br ++autofs has somewhat more limited logging and debug logging options. ++When the log_options options is encountered it is converted to the ++nearest matching autofs logging option. Since the configuration ++option debug_options would be handled the same way it is ignored. ++.TP ++.B restart_mounts ++.br ++This option has no sensible meaning within autofs because autofs ++always tries to re-connect to existing mounts. While this has its ++own set of problems not re-connecting to existing mounts always ++results in a non-functional automount tree if mounts were busy at ++the last shutdown (as is also the case with amd when using ++mount_type autofs). ++.TP ++.B forced_unmounts ++.br ++Detaching mounts often causes serious problems for users of ++existing mounts. It is used by autofs in some cases, either at ++the explicit request of the user (with a command line or init ++option) and in some special cases during program operation but ++is avoided whenever possible. ++.P ++A number of configuration options are not yet implemented: ++.TP ++.B search_path ++.br ++Always a little frustrating, the compiled in map location should ++be used to locate maps but isn't in some cases. This requires ++work within autofs itself and that will (obviously) include ++implementing this configuration option for the amd map parser ++as well. ++.TP ++.B fully_qualified_hosts ++Not yet implemented. ++.TP ++.B unmount_on_exit ++.br ++Since autofs always tries to re-connect to mounts left mounted ++from a previous shutdown this is a sensible option to implement ++and that will be done. ++.TP ++.B browsable_dirs ++.br ++Not yet implemented. ++.TP ++.B exec_map_timeout ++.br ++A timeout is not currently used for for program maps, might be ++implemented. ++.TP ++.B tag ++.br ++The tag option is not implemented within autofs. ++.P ++Supported options: ++.TP ++.BR arch ", " karch ", " os ", " osver ++.br ++These options default to what is returned from uname(2) and can ++be overridden if required. ++.TP ++.B full_os ++This option has no default and must be set in the configuration ++if used in maps. ++.TP ++.B cluster ++.br ++If not set defaults to the host domain name. This option corresponds ++to the HP_UX cluster name (according to the amd source) and is ++probably not used in Linux but is set anyway. ++.TP ++.B vendor ++This option has a default value of "unknown", it must be set in the ++configuration if used in maps. ++.TP ++.B auto_dir ++.br ++Is the base name of the mount tree used for external mounts that ++are sometimes needed by amd maps. Its default value is "/a". ++.TP ++.B map_type ++.br ++Specifies the autofs map source, such as file, nis, ldap etc. and ++has no default value set. ++.TP ++.B map_defaults ++.br ++This option is used to override /defaults entries within maps ++and can be used to provide different defaults on specific machines ++without having to modify centrally managed maps. It is empty by ++default. ++.TP ++.B dismount_interval ++.br ++Is equivalent to the autofs timeout option. It is only possible ++to use this with type "auto" mounts due to the way the autofs ++kernel module performs expiry. It takes its default value from ++the autofs internal defaulti of 600 seconds. ++.TP ++.B autofs_use_lofs ++.br ++If set to "yes" autofs will attempt to use bind mounts for type ++"auto" when possible. ++.TP ++.B nis_domain ++.br ++Allows setting of a domain name other than the system default. ++.TP ++.B local_domain ++.br ++Is used to override (or set) the host domain name. ++.TP ++.B normalize_hostnames ++.br ++If set to "yes" then the contents of ${rhost} is translated in ++its official host name. ++.TP ++.B domain_strip ++.br ++If set to "yes" the domain name part of the host is strippped ++when normalizing hostnames. This can be useful when using of ++the same maps in a multiple domain environment. ++.TP ++.B normalize_slashes ++.br ++This option is set to "yes" by default and will collapse ++multiple unescaped occurrences of "/" to a single "/". ++.TP ++.BR selectors_in_defaults ", " selectors_on_default ++.br ++This option has a default value of "no". If set to "yes" then ++any defaults entry will be checked for selectors to determine ++the values to be used. selectors_in_defaults is the preferred ++option to use. ++.TP ++.B ldap_base ++.br ++iThis option has no default value. It must be set to the base dn ++that is used for queries if ldap is to be used as a map source. ++.TP ++.B ldap_hostports ++.br ++This option has no default value set. It must be set to the URI ++of the LDAP server to be used for lookups wheni ldap is used a ++map source. It may contain a comma or space seperated list of ++LDAP URIs. ++.TP ++.B hesiod_base ++.br ++Sets the base name used for hesiod map sources. ++.SH EXAMPLE ++.sp ++.RS +.2i ++.ta 1.0i ++.nf ++[ autofs ] ++timeout = 300 ++browse_mode = no ++ ++[ amd ] ++dismount_interval = 300 ++map_type = nis ++autofs_use_lofs = no ++ ++[ /expamle/mount ] ++dismount_interval = 60 ++map_type = file ++.fi ++.RE ++.SH "SEE ALSO" ++.BR automount (8), ++.BR auto.master (5), ++.BR autofs_ldap_auth.conf (5) ++.SH AUTHOR ++This manual page was written by Ian Kent . +diff --git a/man/autofs_ldap_auth.conf.5.in b/man/autofs_ldap_auth.conf.5.in +index fa23ce5..fe5077d 100644 +--- a/man/autofs_ldap_auth.conf.5.in ++++ b/man/autofs_ldap_auth.conf.5.in +@@ -113,5 +113,6 @@ externally configured credential cache that is used during authentication. + By default, autofs will setup a memory based credential cache. + .SH "SEE ALSO" + .BR auto.master (5), ++.BR autofs.conf (5), + .SH AUTHOR + This manual page was written by Ian Kent . +diff --git a/man/automount.8 b/man/automount.8 +index 79e53f0..130b24c 100644 +--- a/man/automount.8 ++++ b/man/automount.8 +@@ -172,6 +172,7 @@ constructed has been detached from the mount tree. + .SH "SEE ALSO" + .BR autofs (5), + .BR autofs (8), ++.BR autofs.conf (5), + .BR auto.master (5), + .BR mount (8). + .BR autofs_ldap_auth.conf (5) diff --git a/SOURCES/autofs-5.0.9-amd-lookup-use-config-map_type-if-type-is-not-given.patch b/SOURCES/autofs-5.0.9-amd-lookup-use-config-map_type-if-type-is-not-given.patch new file mode 100644 index 0000000..dba91f1 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-use-config-map_type-if-type-is-not-given.patch @@ -0,0 +1,62 @@ +autofs-5.0.9 - amd lookup use config map_type if type is not given + +From: Ian Kent + +If the map type isn't given in the map defaults or the map location +the attempt to set it from the configuration. + +A NULL map type is valid and means use the nss source list to find +the source of the map. + +This approach may not always give the best result. For example, when +a map type specified in the master map submounts will not inherit +it and will instead use a configured global type instead. Second, +if we want to use nss to find a map source a global map type can't +be defined or it will override the nss source search. +--- + modules/parse_amd.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index e27a195..bf673b3 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -1339,12 +1339,21 @@ struct amd_entry *make_default_entry(struct autofs_point *ap, + char *defaults = "opts:=rw,defaults"; + struct amd_entry *defaults_entry; + struct list_head dflts; ++ char *map_type; + + INIT_LIST_HEAD(&dflts); + if (amd_parse_list(ap, defaults, &dflts, &sv)) + return NULL; + defaults_entry = list_entry(dflts.next, struct amd_entry, list); + list_del_init(&defaults_entry->list); ++ /* ++ * If map type isn't given try to inherit from ++ * parent. A NULL map type is valid and means ++ * use configured nss sources. ++ */ ++ map_type = conf_amd_get_map_type(ap->path); ++ if (map_type) ++ defaults_entry->map_type = strdup(map_type); + /* The list should now be empty .... */ + free_amd_entry_list(&dflts); + return defaults_entry; +@@ -1458,6 +1467,16 @@ static struct amd_entry *get_defaults_entry(struct autofs_point *ap, + if (amd_parse_list(ap, expand, &dflts, &sv)) + goto out; + entry = select_default_entry(ap, &dflts, sv); ++ if (!entry->map_type) { ++ /* ++ * If map type isn't given try to inherit from ++ * parent. A NULL map type is valid and means ++ * use configured nss sources. ++ */ ++ char *map_type = conf_amd_get_map_type(ap->path); ++ if (map_type) ++ entry->map_type = strdup(map_type); ++ } + free(expand); + } + diff --git a/SOURCES/autofs-5.0.9-amd-lookup-use-flags-in-map_source-for-format.patch b/SOURCES/autofs-5.0.9-amd-lookup-use-flags-in-map_source-for-format.patch new file mode 100644 index 0000000..9300486 --- /dev/null +++ b/SOURCES/autofs-5.0.9-amd-lookup-use-flags-in-map_source-for-format.patch @@ -0,0 +1,64 @@ +autofs-5.0.9 - amd lookup use flags in map_source for format + +From: Ian Kent + +We will need to check the map format several times so add a flags +field to the map_source struct so we don't need to use strcmp() +every time. +--- + daemon/lookup.c | 2 ++ + include/master.h | 3 +++ + lib/master.c | 4 ++++ + 3 files changed, 9 insertions(+) + +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -476,6 +476,7 @@ static enum nsswitch_status read_map_sou + } + + this->source[4] = '\0'; ++ tmap.flags = map->flags; + tmap.type = this->source; + tmap.format = map->format; + tmap.lookup = map->lookup; +@@ -879,6 +880,7 @@ static enum nsswitch_status lookup_map_n + } + + this->source[4] = '\0'; ++ tmap.flags = map->flags; + tmap.type = this->source; + tmap.format = map->format; + tmap.mc = map->mc; +--- autofs-5.0.7.orig/include/master.h ++++ autofs-5.0.7/include/master.h +@@ -20,7 +20,10 @@ + #ifndef MASTER_H + #define MASTER_H + ++#define MAP_FLAG_FORMAT_AMD 0x0001 ++ + struct map_source { ++ unsigned int flags; + char *type; + char *format; + time_t exp_timeout; /* Timeout for expiring mounts */ +--- autofs-5.0.7.orig/lib/master.c ++++ autofs-5.0.7/lib/master.c +@@ -178,6 +178,8 @@ master_add_map_source(struct master_mape + return NULL; + } + source->format = nformat; ++ if (!strcmp(nformat, "amd")) ++ source->flags |= MAP_FLAG_FORMAT_AMD; + } + + source->age = age; +@@ -430,6 +432,8 @@ master_add_source_instance(struct map_so + return NULL; + } + new->format = nformat; ++ if (!strcmp(nformat, "amd")) ++ new->flags |= MAP_FLAG_FORMAT_AMD; + } + + new->age = age; diff --git a/SOURCES/autofs-5.0.9-check-for-non-existent-negative-entries-in-lookup_ghost.patch b/SOURCES/autofs-5.0.9-check-for-non-existent-negative-entries-in-lookup_ghost.patch new file mode 100644 index 0000000..cd7c140 --- /dev/null +++ b/SOURCES/autofs-5.0.9-check-for-non-existent-negative-entries-in-lookup_ghost.patch @@ -0,0 +1,40 @@ +autofs-5.0.9 - check for non existent negative entries in lookup_ghost() + +From: Ian Kent + +Map entries that have been created in the cache due to a negative lookup +but don't exist in the map source shouldn't have directories created. +In fact map entries that are negative shouldn't have directories created +at all since they should have neen created befor the entry became negative. +--- + CHANGELOG | 1 + + daemon/lookup.c | 8 ++++++++ + 2 files changed, 9 insertions(+) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -72,6 +72,7 @@ + - fix protmap not trying proto v2. + - fix negative status being reset on map read. + - fix fix negative status being reset on map read. ++- check for non existent negative entries in lookup_ghost(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -604,6 +604,14 @@ int lookup_ghost(struct autofs_point *ap + cache_readlock(mc); + me = cache_enumerate(mc, NULL); + while (me) { ++ /* ++ * Map entries that have been created in the cache ++ * due to a negative lookup shouldn't have directories ++ * created if they haven't already been created. ++ */ ++ if (!me->mapent) ++ goto next; ++ + if (!strcmp(me->key, "*")) + goto next; + diff --git a/SOURCES/autofs-5.0.9-fix-fix-negative-status-being-reset-on-map-read.patch b/SOURCES/autofs-5.0.9-fix-fix-negative-status-being-reset-on-map-read.patch new file mode 100644 index 0000000..327c81d --- /dev/null +++ b/SOURCES/autofs-5.0.9-fix-fix-negative-status-being-reset-on-map-read.patch @@ -0,0 +1,42 @@ +autofs-5.0.9 - fix fix negative status being reset on map read + +From: Ian Kent + +The original patch to fix the negative status being reset on map +read caused a regression for the case where a negative entry was +created as a result of a lookup matching the wildcard entry. + +It isn't possible to eliminate the key not found in map messages +on map read for this case because there's no way of knowing if +a map change would have fixed the original problem so the negative +entry status must be reset and the mount retried on each map read. +--- + CHANGELOG | 1 + + daemon/lookup.c | 5 ++++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -71,6 +71,7 @@ + - fix rpc_portmap_getport() proto not set. + - fix protmap not trying proto v2. + - fix negative status being reset on map read. ++- fix fix negative status being reset on map read. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -1041,8 +1041,11 @@ void lookup_prune_one_cache(struct autof + /* + * Reset time of last fail for valid map entries to + * force entry update and subsequent mount retry. ++ * A map entry that's still invalid after a read ++ * may have been created by a failed wildcard lookup ++ * so reset the status on those too. + */ +- if (me->mapent) ++ if (me->mapent || cache_lookup(mc, "*")) + me->status = 0; + me = cache_enumerate(mc, me); + continue; diff --git a/SOURCES/autofs-5.0.9-fix-mistake-in-assignment.patch b/SOURCES/autofs-5.0.9-fix-mistake-in-assignment.patch new file mode 100644 index 0000000..bd3ff22 --- /dev/null +++ b/SOURCES/autofs-5.0.9-fix-mistake-in-assignment.patch @@ -0,0 +1,40 @@ +autofs-5.0.9 - fix mistake in assignment + +From: Ian Kent + +Fix an obvious mistake in an accumulation assignment. +--- + CHANGELOG | 1 + + lib/mounts.c | 4 ++-- + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -103,6 +103,7 @@ + - fixes for samples/auto.master. + - fix variable substitution description. + - fix incorrect append options description in README.v5-release. ++- fix mistake in assignment. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/mounts.c ++++ autofs-5.0.7/lib/mounts.c +@@ -1932,7 +1932,7 @@ int clean_stale_multi_triggers(struct au + /* Check for and umount stale subtree offsets */ + oe_base = oe->key + strlen(root); + ret = clean_stale_multi_triggers(ap, oe, root, oe_base); +- left =+ ret; ++ left += ret; + if (ret) + continue; + +@@ -1977,7 +1977,7 @@ int clean_stale_multi_triggers(struct au + key = strdup(oe->key); + if (!key) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, "malloc: %s", estr); ++ error(ap->logopt, "malloc: %s", estr); + left++; + continue; + } diff --git a/SOURCES/autofs-5.0.9-fix-race-accessing-qdn-in-get_query_dn.patch b/SOURCES/autofs-5.0.9-fix-race-accessing-qdn-in-get_query_dn.patch new file mode 100644 index 0000000..85d651a --- /dev/null +++ b/SOURCES/autofs-5.0.9-fix-race-accessing-qdn-in-get_query_dn.patch @@ -0,0 +1,48 @@ +autofs-5.0.9 - fix race accessing qdn in get_query_dn() + +From: Ian Kent + +Fix a couple of obvious problems in get_query_dn(). + +First, check dn is not NULL before attempting to duplicate it. +And also protect the update of qdn in the context by a mutex. +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 9 ++++++--- + 2 files changed, 7 insertions(+), 3 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -129,6 +129,7 @@ + - add serialization to sasl init. + - dont allocate dev_ctl_ops too early. + - fix incorrect round robin host detection. ++- fix race accessing qdn in get_query_dn(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -461,16 +461,19 @@ static int get_query_dn(unsigned logopt, + } + + free(query); +- qdn = strdup(dn); +- ldap_memfree(dn); ++ if (dn) { ++ qdn = strdup(dn); ++ ldap_memfree(dn); ++ } + ldap_msgfree(result); + if (!qdn) + return 0; + ++ uris_mutex_lock(ctxt); + if (ctxt->qdn) + free(ctxt->qdn); +- + ctxt->qdn = qdn; ++ uris_mutex_unlock(ctxt); + + return 1; + } diff --git a/SOURCES/autofs-5.1.0-add-mutex-call-return-check-in-defaults_c.patch b/SOURCES/autofs-5.1.0-add-mutex-call-return-check-in-defaults_c.patch new file mode 100644 index 0000000..bd2b056 --- /dev/null +++ b/SOURCES/autofs-5.1.0-add-mutex-call-return-check-in-defaults_c.patch @@ -0,0 +1,199 @@ +autofs-5.1.0 - add mutex call return check in defaults.c + +From: Ian Kent + +Even though pthread_mutex_lock() and pthread_mutex_unlock() should +never fail checking their return has very occassionally been useful +and isn't consistent with the usage elsewhere. +--- + CHANGELOG | 1 + + lib/defaults.c | 55 ++++++++++++++++++++++++++++++++++--------------------- + 2 files changed, 35 insertions(+), 21 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -145,6 +145,7 @@ + - fix some out of order evaluations in parse_amd.c. + - fix copy and paste error in dup_defaults_entry(). + - fix leak in parse_mount(). ++- add mutex call return check in defaults.c. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -171,6 +171,19 @@ static int conf_update(const char *, con + static void conf_delete(const char *, const char *); + static struct conf_option *conf_lookup(const char *, const char *); + ++static void defaults_mutex_lock(void) ++{ ++ int status = pthread_mutex_lock(&conf_mutex); ++ if (status) ++ fatal(status); ++} ++ ++static void defaults_mutex_unlock(void) ++{ ++ int status = pthread_mutex_unlock(&conf_mutex); ++ if (status) ++ fatal(status); ++} + + static void message(unsigned int to_syslog, const char *msg, ...) + { +@@ -253,9 +266,9 @@ static void __conf_release(void) + + void defaults_conf_release(void) + { +- pthread_mutex_lock(&conf_mutex); ++ defaults_mutex_lock(); + __conf_release(); +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + return; + } + +@@ -727,11 +740,11 @@ static unsigned int conf_section_exists( + return 0; + + ret = 0; +- pthread_mutex_lock(&conf_mutex); ++ defaults_mutex_lock(); + co = conf_lookup(section, section); + if (co) + ret = 1; +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + + return ret; + } +@@ -1057,7 +1070,7 @@ unsigned int defaults_read_config(unsign + + conf = oldconf = NULL; + +- pthread_mutex_lock(&conf_mutex); ++ defaults_mutex_lock(); + if (!config) { + if (conf_init()) { + message(to_syslog, "failed to init config"); +@@ -1149,7 +1162,7 @@ out: + fclose(conf); + if (oldconf) + fclose(oldconf); +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + return ret; + } + +@@ -1158,11 +1171,11 @@ static char *conf_get_string(const char + struct conf_option *co; + char *val = NULL; + +- pthread_mutex_lock(&conf_mutex); ++ defaults_mutex_lock(); + co = conf_lookup(section, name); + if (co && co->value) + val = strdup(co->value); +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + return val; + } + +@@ -1171,11 +1184,11 @@ static long conf_get_number(const char * + struct conf_option *co; + long val = -1; + +- pthread_mutex_lock(&conf_mutex); ++ defaults_mutex_lock(); + co = conf_lookup(section, name); + if (co && co->value) + val = atol(co->value); +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + return val; + } + +@@ -1184,7 +1197,7 @@ static int conf_get_yesno(const char *se + struct conf_option *co; + int val = -1; + +- pthread_mutex_lock(&conf_mutex); ++ defaults_mutex_lock(); + co = conf_lookup(section, name); + if (co && co->value) { + if (isdigit(*co->value)) +@@ -1194,7 +1207,7 @@ static int conf_get_yesno(const char *se + else if (!strcasecmp(co->value, "no")) + val = 0; + } +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + return val; + } + +@@ -1271,10 +1284,10 @@ struct list_head *defaults_get_uris(void + return NULL; + } + +- pthread_mutex_lock(&conf_mutex); ++ defaults_mutex_lock(); + co = conf_lookup(autofs_gbl_sec, NAME_LDAP_URI); + if (!co) { +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + free(list); + return NULL; + } +@@ -1285,7 +1298,7 @@ struct list_head *defaults_get_uris(void + add_uris(co->value, list); + co = co->next; + } +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + + if (list_empty(list)) { + free(list); +@@ -1397,10 +1410,10 @@ struct ldap_searchdn *defaults_get_searc + if (!defaults_read_config(0)) + return NULL; + +- pthread_mutex_lock(&conf_mutex); ++ defaults_mutex_lock(); + co = conf_lookup(autofs_gbl_sec, NAME_SEARCH_BASE); + if (!co) { +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + return NULL; + } + +@@ -1416,7 +1429,7 @@ struct ldap_searchdn *defaults_get_searc + + new = alloc_searchdn(co->value); + if (!new) { +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + defaults_free_searchdns(sdn); + return NULL; + } +@@ -1433,7 +1446,7 @@ struct ldap_searchdn *defaults_get_searc + + co = co->next; + } +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + + return sdn; + } +@@ -1511,9 +1524,9 @@ int defaults_master_set(void) + { + struct conf_option *co; + +- pthread_mutex_lock(&conf_mutex); ++ defaults_mutex_lock(); + co = conf_lookup(autofs_gbl_sec, NAME_MASTER_MAP); +- pthread_mutex_unlock(&conf_mutex); ++ defaults_mutex_unlock(); + if (co) + return 1; + return 0; diff --git a/SOURCES/autofs-5.1.0-add-return-check-in-ldap-check_map_indirect.patch b/SOURCES/autofs-5.1.0-add-return-check-in-ldap-check_map_indirect.patch new file mode 100644 index 0000000..4609bf8 --- /dev/null +++ b/SOURCES/autofs-5.1.0-add-return-check-in-ldap-check_map_indirect.patch @@ -0,0 +1,68 @@ +autofs-5.1.0 - add return check in ldap check_map_indirect() + +From: Ian Kent + +Fix not checking return from pthread_mutex_lock/pthread_mutex_unlock in +modules/lookup_ldap.c:check_map_indirect(). +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 17 +++++++++++++---- + 2 files changed, 14 insertions(+), 4 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -139,6 +139,7 @@ + - fix leak in get_network_proximity(). + - fix buffer size checks in merge_options(). + - check amd lex buffer len before copy. ++- add return check in ldap check_map_indirect(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -3420,12 +3420,15 @@ static int check_map_indirect(struct aut + time_t now = time(NULL); + time_t t_last_read; + int ret, cur_state; ++ int status; + + mc = source->mc; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + +- pthread_mutex_lock(&ap->entry->current_mutex); ++ status = pthread_mutex_lock(&ap->entry->current_mutex); ++ if (status) ++ fatal(status); + if (is_amd_format) { + unsigned long timestamp = get_amd_timestamp(ctxt); + if (timestamp > ctxt->timestamp) { +@@ -3445,7 +3448,9 @@ static int check_map_indirect(struct aut + ctxt->check_defaults = 0; + } + } +- pthread_mutex_unlock(&ap->entry->current_mutex); ++ status = pthread_mutex_unlock(&ap->entry->current_mutex); ++ if (status) ++ fatal(status); + + ret = match_key(ap, source, key, key_len, ctxt); + if (ret == CHE_FAIL) { +@@ -3490,10 +3495,14 @@ static int check_map_indirect(struct aut + } + cache_unlock(mc); + +- pthread_mutex_lock(&ap->entry->current_mutex); ++ status = pthread_mutex_lock(&ap->entry->current_mutex); ++ if (status) ++ fatal(status); + if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) + source->stale = 1; +- pthread_mutex_unlock(&ap->entry->current_mutex); ++ status = pthread_mutex_unlock(&ap->entry->current_mutex); ++ if (status) ++ fatal(status); + } + + cache_readlock(mc); diff --git a/SOURCES/autofs-5.1.0-add-serialization-to-sasl-init.patch b/SOURCES/autofs-5.1.0-add-serialization-to-sasl-init.patch new file mode 100644 index 0000000..8ed0796 --- /dev/null +++ b/SOURCES/autofs-5.1.0-add-serialization-to-sasl-init.patch @@ -0,0 +1,92 @@ +autofs-5.1.0 - add serialization to sasl init + +From: Ian Kent + +Attempt to resolve crash in sasl initialization. We know that the +initial connection calls to connect to an LDAP server are not +thread safe and it looks like the sasl code doesn't take that into +consideration so adding serialization with a mutex is probably a +sensible thing to do. +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 13 +++++++++++++ + 2 files changed, 14 insertions(+) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -126,6 +126,7 @@ + - cleanup options in amd_parse.c + - allow empty value for some map options. + - allow empty value in macro selectors. ++- add serialization to sasl init. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -578,7 +578,9 @@ static int do_bind(unsigned logopt, LDAP + ctxt->auth_required, ctxt->sasl_mech); + + if (ctxt->auth_required & LDAP_NEED_AUTH) { ++ ldapinit_mutex_lock(); + rv = autofs_sasl_bind(logopt, ldap, ctxt); ++ ldapinit_mutex_unlock(); + debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv); + } else { + rv = bind_ldap_simple(logopt, ldap, uri, ctxt); +@@ -922,7 +924,9 @@ static LDAP *do_reconnect(unsigned logop + #ifdef WITH_SASL + /* Dispose of the sasl authentication connection and try again. */ + if (!ldap && ctxt->auth_required & LDAP_NEED_AUTH) { ++ ldapinit_mutex_lock(); + autofs_sasl_dispose(ctxt); ++ ldapinit_mutex_unlock(); + ldap = connect_to_server(logopt, ctxt->server, ctxt); + } + #endif +@@ -958,7 +962,9 @@ static LDAP *do_reconnect(unsigned logop + * current server again before trying other servers in the list. + */ + if (!ldap && ctxt->auth_required & LDAP_NEED_AUTH) { ++ ldapinit_mutex_lock(); + autofs_sasl_dispose(ctxt); ++ ldapinit_mutex_unlock(); + ldap = connect_to_server(logopt, ctxt->uri->uri, ctxt); + } + #endif +@@ -969,7 +975,9 @@ static LDAP *do_reconnect(unsigned logop + + find_server: + #ifdef WITH_SASL ++ ldapinit_mutex_lock(); + autofs_sasl_dispose(ctxt); ++ ldapinit_mutex_unlock(); + #endif + + /* Current server failed, try the rest or dc connection */ +@@ -1742,11 +1750,14 @@ int lookup_init(const char *mapfmt, int + + #ifdef WITH_SASL + /* Init the sasl callbacks */ ++ ldapinit_mutex_lock(); + if (!autofs_sasl_client_init(LOGOPT_NONE)) { + error(LOGOPT_ANY, "failed to init sasl client"); ++ ldapinit_mutex_unlock(); + free_context(ctxt); + return 1; + } ++ ldapinit_mutex_unlock(); + #endif + + if (is_amd_format) +@@ -3678,8 +3689,10 @@ int lookup_done(void *context) + struct lookup_context *ctxt = (struct lookup_context *) context; + int rv = close_parse(ctxt->parse); + #ifdef WITH_SASL ++ ldapinit_mutex_lock(); + autofs_sasl_dispose(ctxt); + autofs_sasl_done(); ++ ldapinit_mutex_unlock(); + #endif + free_context(ctxt); + return rv; diff --git a/SOURCES/autofs-5.1.0-beta1-add-plus-to-path-match-pattern.patch b/SOURCES/autofs-5.1.0-beta1-add-plus-to-path-match-pattern.patch new file mode 100644 index 0000000..224f399 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-add-plus-to-path-match-pattern.patch @@ -0,0 +1,39 @@ +autofs-5.1.0-beta1 - add plus to path match pattern + +From: Ian Kent + +The pattern matching in the tokenizer is very strict and quite +limited. That's been done (initially) to ensure that the parsing +of other parts of map entries is accurate and to ensure that +error cases are handled cleanly since the strict matching will +cause errors. + +I don't want to open up patterns that probably need it to accept +a wide range of characters just yet but adding "+" to the match +is obviously needed. +--- + CHANGELOG | 1 + + modules/amd_tok.l | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -121,6 +121,7 @@ + - fix ldap_uri config update. + - fix typo in conf_load_autofs_defaults(). + - fix hash on confg option add and delete. ++- add plus to path match pattern. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/amd_tok.l ++++ autofs-5.0.7/modules/amd_tok.l +@@ -81,7 +81,7 @@ V4NUM ([01]?[0-9][0-9]?|2[0-4][0-9]|25[ + MACRO (\$\{([[:alpha:]_/]([[:alnum:]_\-])([[:alnum:]_\-/])*)\}) + QSTR (\"([^"\\]|\\.)*\") + OSTR ([[:alpha:]]([[:alnum:]_\-])+) +-FSTR ([[:alnum:]_/\.]([[:alnum:]_\-/\.]|(\\.))*) ++FSTR ([[:alnum:]_/\.]([[:alnum:]_\-/\+\.]|(\\.))*) + VSTR (([[:alnum:]_\-\:/\.])+) + SSTR ([[:alpha:]]([[:alnum:]\-\.])+) + IP4ADDR ({V4NUM}\.((({V4NUM}\.){0,2}){V4NUM}?)) diff --git a/SOURCES/autofs-5.1.0-beta1-allow-empty-value-for-some-map-options.patch b/SOURCES/autofs-5.1.0-beta1-allow-empty-value-for-some-map-options.patch new file mode 100644 index 0000000..a55c6f5 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-allow-empty-value-for-some-map-options.patch @@ -0,0 +1,570 @@ +autofs-5.1.0-beta1 - allow empty value for some map options + +From: Ian Kent + +Some map options may be given but left blank, possibly with the intent +the mount location mount attempt will not be done or fail, such as when +the delay option is also given. + +autofs doesn't implement the delay option but it shouldn't fail to parse +these locations so that a valid locations in the list can be tried. +--- + CHANGELOG | 1 + lib/parse_subs.c | 12 +++- + modules/amd_parse.y | 36 ++++++++++++++ + modules/amd_tok.l | 35 ++++++++++++-- + modules/parse_amd.c | 125 ++++++++++++++++++++++++++++++++-------------------- + 5 files changed, 155 insertions(+), 54 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -124,6 +124,7 @@ + - add plus to path match pattern. + - fix multi entry ldap option handling. + - cleanup options in amd_parse.c ++- allow empty value for some map options. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/parse_subs.c ++++ autofs-5.0.7/lib/parse_subs.c +@@ -889,14 +889,20 @@ char *merge_options(const char *opt1, co + char *tok, *ptr = NULL; + size_t len; + +- if (!opt1 && !opt2) ++ if ((!opt1 || !*opt1) && (!opt2 || !*opt2)) + return NULL; + +- if (!opt2) ++ if (!opt2 || !*opt2) { ++ if (!*opt1) ++ return NULL; + return strdup(opt1); ++ } + +- if (!opt1) ++ if (!opt1 || !*opt1) { ++ if (!*opt2) ++ return NULL; + return strdup(opt2); ++ } + + if (!strcmp(opt1, opt2)) + return strdup(opt1); +--- autofs-5.0.7.orig/modules/amd_parse.y ++++ autofs-5.0.7/modules/amd_parse.y +@@ -335,6 +335,15 @@ option_assignment: MAP_OPTION OPTION_ASS + YYABORT; + } + } ++ | MAP_OPTION OPTION_ASSIGN ++ { ++ if (!strcmp($1, "fs")) ++ entry.fs = amd_strdup(""); ++ else { ++ amd_notify($1); ++ YYABORT; ++ } ++ } + | FS_OPTION OPTION_ASSIGN FS_OPT_VALUE + { + if (!strcmp($1, "rhost")) +@@ -358,6 +367,19 @@ option_assignment: MAP_OPTION OPTION_ASS + YYABORT; + } + } ++ | FS_OPTION OPTION_ASSIGN ++ { ++ if (!strcmp($1, "rhost")) ++ entry.rhost = amd_strdup(""); ++ else if (!strcmp($1, "rfs")) ++ entry.rfs = amd_strdup(""); ++ else if (!strcmp($1, "dev")) ++ entry.dev = amd_strdup(""); ++ else { ++ amd_notify($1); ++ YYABORT; ++ } ++ } + | MNT_OPTION OPTION_ASSIGN options + { + memset(opts, 0, sizeof(opts)); +@@ -370,6 +392,20 @@ option_assignment: MAP_OPTION OPTION_ASS + else { + amd_notify($1); + YYABORT; ++ } ++ } ++ | MNT_OPTION OPTION_ASSIGN ++ { ++ memset(opts, 0, sizeof(opts)); ++ if (!strcmp($1, "opts")) ++ entry.opts = amd_strdup(""); ++ else if (!strcmp($1, "addopts")) ++ entry.addopts = amd_strdup(""); ++ else if (!strcmp($1, "remopts")) ++ entry.remopts = amd_strdup(""); ++ else { ++ amd_notify($1); ++ YYABORT; + } + } + | MAP_OPTION OPTION_ASSIGN CACHE_OPTION +--- autofs-5.0.7.orig/modules/amd_tok.l ++++ autofs-5.0.7/modules/amd_tok.l +@@ -177,9 +177,14 @@ CUTSEP (\|\||\/) + } + + { +- {NL} | ++ {NL} { ++ BEGIN(INITIAL); ++ yyless(1); ++ } ++ + \x00 { + BEGIN(INITIAL); ++ return SEPERATOR; + yyless(1); + } + +@@ -217,9 +222,14 @@ CUTSEP (\|\||\/) + } + + { +- {NL} | ++ {NL} { ++ BEGIN(INITIAL); ++ yyless(1); ++ } ++ + \x00 { + BEGIN(INITIAL); ++ return SEPERATOR; + yyless(1); + } + +@@ -242,9 +252,14 @@ CUTSEP (\|\||\/) + } + + { +- {NL} | ++ {NL} { ++ BEGIN(INITIAL); ++ yyless(1); ++ } ++ + \x00 { + BEGIN(INITIAL); ++ return SEPERATOR; + yyless(1); + } + +@@ -269,9 +284,14 @@ CUTSEP (\|\||\/) + } + + { +- {NL} | ++ {NL} { ++ BEGIN(INITIAL); ++ yyless(1); ++ } ++ + \x00 { + BEGIN(INITIAL); ++ return SEPERATOR; + yyless(1); + } + +@@ -296,9 +316,14 @@ CUTSEP (\|\||\/) + } + + { +- {NL} | ++ {NL} { ++ BEGIN(INITIAL); ++ yyless(1); ++ } ++ + \x00 { + BEGIN(INITIAL); ++ return SEPERATOR; + yyless(1); + } + +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -683,7 +683,7 @@ static struct substvar *expand_entry(str + unsigned int logopt = ap->logopt; + char *expand; + +- if (entry->rhost) { ++ if (entry->rhost && *entry->rhost) { + char *host = strdup(entry->rhost); + char *nn; + if (!host) { +@@ -720,7 +720,7 @@ next: + sv = macro_addvar(sv, "sublink", 7, entry->sublink); + } + +- if (entry->rfs) { ++ if (entry->rfs && *entry->rfs) { + if (expand_selectors(ap, entry->rfs, &expand, sv)) { + debug(logopt, MODPREFIX + "rfs expand(\"%s\") -> %s", entry->rfs, expand); +@@ -730,7 +730,7 @@ next: + sv = macro_addvar(sv, "rfs", 3, entry->rfs); + } + +- if (entry->fs) { ++ if (entry->fs && *entry->fs) { + if (expand_selectors(ap, entry->fs, &expand, sv)) { + debug(logopt, MODPREFIX + "fs expand(\"%s\") -> %s", entry->fs, expand); +@@ -740,7 +740,7 @@ next: + sv = macro_addvar(sv, "fs", 2, entry->fs); + } + +- if (entry->opts) { ++ if (entry->opts && *entry->opts) { + if (expand_selectors(ap, entry->opts, &expand, sv)) { + debug(logopt, MODPREFIX + "ops expand(\"%s\") -> %s", entry->opts, expand); +@@ -750,7 +750,7 @@ next: + sv = macro_addvar(sv, "opts", 4, entry->opts); + } + +- if (entry->addopts) { ++ if (entry->addopts && *entry->addopts) { + if (expand_selectors(ap, entry->addopts, &expand, sv)) { + debug(logopt, MODPREFIX + "addopts expand(\"%s\") -> %s", +@@ -761,7 +761,7 @@ next: + sv = macro_addvar(sv, "addopts", 7, entry->addopts); + } + +- if (entry->remopts) { ++ if (entry->remopts && *entry->remopts) { + if (expand_selectors(ap, entry->remopts, &expand, sv)) { + debug(logopt, MODPREFIX + "remopts expand(\"%s\") -> %s", +@@ -781,7 +781,7 @@ static void expand_merge_options(struct + { + char *tmp; + +- if (entry->opts) { ++ if (entry->opts && *entry->opts) { + if (!expand_selectors(ap, entry->opts, &tmp, sv)) + error(ap->logopt, MODPREFIX "failed to expand opts"); + else { +@@ -790,7 +790,7 @@ static void expand_merge_options(struct + } + } + +- if (entry->addopts) { ++ if (entry->addopts && *entry->addopts) { + if (!expand_selectors(ap, entry->addopts, &tmp, sv)) + error(ap->logopt, MODPREFIX "failed to expand addopts"); + else { +@@ -799,7 +799,7 @@ static void expand_merge_options(struct + } + } + +- if (entry->remopts) { ++ if (entry->remopts && *entry->remopts) { + if (!expand_selectors(ap, entry->remopts, &tmp, sv)) + error(ap->logopt, MODPREFIX "failed to expand remopts"); + else { +@@ -832,11 +832,13 @@ static struct substvar *merge_entry_opti + entry->opts = tmp; + sv = macro_addvar(sv, "opts", 4, entry->opts); + } +- tmp = strdup(entry->opts); +- if (tmp) { +- free(entry->remopts); +- entry->remopts = tmp; +- sv = macro_addvar(sv, "remopts", 7, entry->remopts); ++ if (*entry->opts) { ++ tmp = strdup(entry->opts); ++ if (tmp) { ++ free(entry->remopts); ++ entry->remopts = tmp; ++ sv = macro_addvar(sv, "remopts", 7, entry->remopts); ++ } + } + return sv; + } +@@ -853,7 +855,7 @@ static struct substvar *merge_entry_opti + entry->opts = tmp; + sv = macro_addvar(sv, "opts", 4, entry->opts); + } +- } else if (entry->addopts) { ++ } else if (entry->addopts && *entry->addopts) { + tmp = strdup(entry->addopts); + if (tmp) { + info(ap->logopt, MODPREFIX +@@ -875,7 +877,7 @@ static struct substvar *merge_entry_opti + entry->remopts = tmp; + sv = macro_addvar(sv, "remopts", 7, entry->remopts); + } +- } else if (entry->addopts) { ++ } else if (entry->addopts && *entry->addopts) { + tmp = strdup(entry->addopts); + if (tmp) { + info(ap->logopt, MODPREFIX +@@ -910,6 +912,7 @@ static int do_link_mount(struct autofs_p + struct amd_entry *entry, unsigned int flags) + { + char target[PATH_MAX + 1]; ++ const char *opts = (entry->opts && *entry->opts) ? entry->opts : NULL; + int ret; + + if (entry->sublink) +@@ -922,7 +925,7 @@ static int do_link_mount(struct autofs_p + + /* For a sublink this might cause an external mount */ + ret = do_mount(ap, ap->path, +- name, strlen(name), target, "bind", entry->opts); ++ name, strlen(name), target, "bind", opts); + if (!ret) + goto out; + +@@ -967,12 +970,13 @@ static int do_generic_mount(struct autof + struct amd_entry *entry, const char *target, + unsigned int flags) + { ++ const char *opts = (entry->opts && *entry->opts) ? entry->opts : NULL; + unsigned int umount = 0; + int ret = 0; + + if (!entry->fs) { +- ret = do_mount(ap, ap->path, name, strlen(name), +- target, entry->type, entry->opts); ++ ret = do_mount(ap, ap->path, name, ++ strlen(name), target, entry->type, opts); + } else { + /* + * Careful, external mounts may get mounted +@@ -981,7 +985,7 @@ static int do_generic_mount(struct autof + */ + if (!is_mounted(_PATH_MOUNTED, entry->fs, MNTS_REAL)) { + ret = do_mount(ap, entry->fs, "/", 1, +- target, entry->type, entry->opts); ++ target, entry->type, opts); + if (ret) + goto out; + umount = 1; +@@ -999,7 +1003,7 @@ static int do_nfs_mount(struct autofs_po + { + char target[PATH_MAX + 1]; + unsigned int proximity; +- char *opts = entry->opts; ++ char *opts = (entry->opts && *entry->opts) ? entry->opts : NULL; + unsigned int umount = 0; + int ret = 0; + +@@ -1008,7 +1012,7 @@ static int do_nfs_mount(struct autofs_po + strcat(target, entry->rfs); + + proximity = get_network_proximity(entry->rhost); +- if (proximity == PROXIMITY_OTHER && entry->remopts) ++ if (proximity == PROXIMITY_OTHER && entry->remopts && *entry->remopts) + opts = entry->remopts; + + if (!entry->fs) { +@@ -1120,7 +1124,7 @@ static int do_host_mount(struct autofs_p + goto out; + } + +- if (entry->opts) { ++ if (entry->opts && *entry->opts) { + argv[0] = entry->opts; + argv[1] = NULL; + pargv = argv; +@@ -1180,9 +1184,13 @@ static unsigned int validate_auto_option + /* + * The amd manual implies all the mount type auto options + * are optional but I don't think there's much point if +- * no map is given. ++ * no map is given. If the option has been intentionally ++ * left blank the mount must be expected to fail so don't ++ * report the error. + */ +- if (!entry->fs) { ++ if (!*entry->fs) ++ return 0; ++ else if (!entry->fs) { + error(logopt, MODPREFIX + "%s: file system not given", entry->type); + return 0; +@@ -1201,11 +1209,19 @@ static unsigned int validate_nfs_options + struct amd_entry *entry) + { + /* +- * Required option rhost will always have a value. +- * It is set from ${host} if it is found to be NULL +- * earlier in the parsing process. ++ * Required option rhost will always have a value unless ++ * it has been intentionally left blank. It is set from ++ * ${host} if it is found to be NULL earlier in the parsing ++ * process. Don't report the error if it has been left blank ++ * or if the fs option has been left blank since the mount is ++ * expected to fail. + */ +- if (!entry->rfs) { ++ if (!entry->rfs || !*entry->rfs) { ++ if (!*entry->rfs) ++ return 0; ++ /* Map option fs has been intentionally left blank */ ++ if (entry->fs && !*entry->fs) ++ return 0; + if (entry->fs) + entry->rfs = strdup(entry->fs); + if (!entry->rfs) { +@@ -1226,14 +1242,22 @@ static unsigned int validate_generic_opt + unsigned long fstype, + struct amd_entry *entry) + { ++ /* ++ * If dev or rfs are empty in the map entry the mount is ++ * expected to fail so don't report the error. ++ */ + if (fstype != AMD_MOUNT_TYPE_LOFS) { +- if (!entry->dev) { ++ if (!*entry->dev) ++ return 0; ++ else if (!entry->dev) { + error(logopt, MODPREFIX + "%s: mount device not given", entry->type); + return 0; + } + } else { +- if (!entry->rfs) { ++ if (!*entry->rfs) ++ return 0; ++ else if (!entry->rfs) { + /* + * Can't use entry->type as the mount type to reprot + * the error since entry->type == "bind" not "lofs". +@@ -1270,11 +1294,14 @@ static unsigned int validate_host_option + struct amd_entry *entry) + { + /* +- * Not really that useful since rhost is always non-null +- * because it will have the the value of the host name if +- * it isn't set in the map entry. ++ * rhost is always non-null, unless it is intentionally left ++ * empty, because it will have the the value of the host name ++ * if it isn't given in the map entry. Don't report an error ++ * if it has been left empty since it's expected to fail. + */ +- if (!entry->rhost) { ++ if (!*entry->rhost) ++ return 0; ++ else if (!entry->rhost) { + error(logopt, MODPREFIX + "%s: remote host name not given", entry->type); + return 0; +@@ -1382,7 +1409,7 @@ void dequote_entry(struct autofs_point * + } + } + +- if (entry->fs) { ++ if (entry->fs && *entry->fs) { + res = dequote(entry->fs, strlen(entry->fs), ap->logopt); + if (res) { + debug(ap->logopt, +@@ -1393,7 +1420,7 @@ void dequote_entry(struct autofs_point * + } + } + +- if (entry->rfs) { ++ if (entry->rfs && *entry->rfs) { + res = dequote(entry->rfs, strlen(entry->rfs), ap->logopt); + if (res) { + debug(ap->logopt, +@@ -1404,7 +1431,7 @@ void dequote_entry(struct autofs_point * + } + } + +- if (entry->opts) { ++ if (entry->opts && *entry->opts) { + res = dequote(entry->opts, strlen(entry->opts), ap->logopt); + if (res) { + debug(ap->logopt, +@@ -1415,7 +1442,7 @@ void dequote_entry(struct autofs_point * + } + } + +- if (entry->remopts) { ++ if (entry->remopts && *entry->remopts) { + res = dequote(entry->remopts, strlen(entry->remopts), ap->logopt); + if (res) { + debug(ap->logopt, +@@ -1426,7 +1453,7 @@ void dequote_entry(struct autofs_point * + } + } + +- if (entry->addopts) { ++ if (entry->addopts && *entry->addopts) { + res = dequote(entry->addopts, strlen(entry->addopts), ap->logopt); + if (res) { + debug(ap->logopt, +@@ -1446,6 +1473,10 @@ static void normalize_sublink(unsigned i + char *new; + size_t len; + ++ /* Normalizing sublink requires a non-blank fs option */ ++ if (!*entry->fs) ++ return; ++ + if (entry->sublink && *entry->sublink != '/') { + len = strlen(entry->fs) + strlen(entry->sublink) + 2; + new = malloc(len); +@@ -1559,37 +1590,39 @@ static struct amd_entry *dup_defaults_en + entry->fs = tmp; + } + +- if (defaults->rfs) { ++ /* These shouldn't be blank in a defaults entry but ... */ ++ ++ if (defaults->rfs && *defaults->rfs) { + tmp = strdup(defaults->rfs); + if (tmp) + entry->rfs = tmp; + } + +- if (defaults->rhost) { ++ if (defaults->rhost && *defaults->rfs) { + tmp = strdup(defaults->rhost); + if (tmp) + entry->rhost = tmp; + } + +- if (defaults->dev) { ++ if (defaults->dev && *defaults->dev) { + tmp = strdup(defaults->dev); + if (tmp) + entry->dev = tmp; + } + +- if (defaults->opts) { ++ if (defaults->opts && *defaults->opts) { + tmp = strdup(defaults->opts); + if (tmp) + entry->opts = tmp; + } + +- if (defaults->addopts) { ++ if (defaults->addopts && *defaults->addopts) { + tmp = strdup(defaults->addopts); + if (tmp) + entry->addopts = tmp; + } + +- if (defaults->remopts) { ++ if (defaults->remopts && *defaults->remopts) { + tmp = strdup(defaults->remopts); + if (tmp) + entry->remopts = tmp; diff --git a/SOURCES/autofs-5.1.0-beta1-allow-empty-value-in-macro-selectors.patch b/SOURCES/autofs-5.1.0-beta1-allow-empty-value-in-macro-selectors.patch new file mode 100644 index 0000000..7e92c4f --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-allow-empty-value-in-macro-selectors.patch @@ -0,0 +1,74 @@ +autofs-5.1.0-beta1 - allow empty value in macro selectors + +From: Ian Kent + +Some map selectors (this case is olny considering macro selectors) may +be given the comparison value left blank, possibly with the intent the +selector will not match so a mount will not be attempted, such as when +the delay option is also given. + +autofs doesn't implement the delay option but it shouldn't fail to parse +these locations so that a valid locations in the list can be tried. +--- + CHANGELOG | 1 + + modules/amd_parse.y | 14 ++++++++++++++ + modules/parse_amd.c | 9 +++++++-- + 3 files changed, 22 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -125,6 +125,7 @@ + - fix multi entry ldap option handling. + - cleanup options in amd_parse.c + - allow empty value for some map options. ++- allow empty value in macro selectors. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/amd_parse.y ++++ autofs-5.0.7/modules/amd_parse.y +@@ -200,12 +200,26 @@ selection: SELECTOR IS_EQUAL SELECTOR_VA + YYABORT; + } + } ++ | SELECTOR IS_EQUAL ++ { ++ if (!make_selector($1, "", NULL, SEL_COMP_EQUAL)) { ++ amd_notify($1); ++ YYABORT; ++ } ++ } + | SELECTOR NOT_EQUAL SELECTOR_VALUE + { + if (!make_selector($1, $3, NULL, SEL_COMP_NOTEQUAL)) { + amd_notify($1); + YYABORT; + } ++ } ++ | SELECTOR NOT_EQUAL ++ { ++ if (!make_selector($1, "", NULL, SEL_COMP_EQUAL)) { ++ amd_notify($1); ++ YYABORT; ++ } + } + | SELECTOR LBRACKET SEL_ARG_VALUE RBRACKET + { +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -350,8 +350,13 @@ static int eval_selector(unsigned int lo + break; + + case SEL_FLAG_NUM: +- res = atoi(v->val); +- val = atoi(s->comp.value); ++ if (!*s->comp.value) { ++ res = 1; ++ val = 0; ++ } else { ++ res = atoi(v->val); ++ val = atoi(s->comp.value); ++ } + if (s->compare & SEL_COMP_EQUAL && res == val) { + debug(logopt, MODPREFIX + "matched selector %s(%s) equal to %s", diff --git a/SOURCES/autofs-5.1.0-beta1-cleanup-options-in-amd_parse-c.patch b/SOURCES/autofs-5.1.0-beta1-cleanup-options-in-amd_parse-c.patch new file mode 100644 index 0000000..3620ce0 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-cleanup-options-in-amd_parse-c.patch @@ -0,0 +1,46 @@ +autofs-5.1.0-beta1 - cleanup options in amd_parse.c + +From: Ian Kent + +Remove useless duplicated memset() calls from mount options handling +in the amd parser. +--- + CHANGELOG | 1 + + modules/amd_parse.y | 13 +++++-------- + 2 files changed, 6 insertions(+), 8 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -123,6 +123,7 @@ + - fix hash on confg option add and delete. + - add plus to path match pattern. + - fix multi entry ldap option handling. ++- cleanup options in amd_parse.c + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/amd_parse.y ++++ autofs-5.0.7/modules/amd_parse.y +@@ -360,17 +360,14 @@ option_assignment: MAP_OPTION OPTION_ASS + } + | MNT_OPTION OPTION_ASSIGN options + { +- if (!strcmp($1, "opts")) { ++ memset(opts, 0, sizeof(opts)); ++ if (!strcmp($1, "opts")) + entry.opts = amd_strdup(opts); +- memset(opts, 0, sizeof(opts)); +- } else if (!strcmp($1, "addopts")) { ++ else if (!strcmp($1, "addopts")) + entry.addopts = amd_strdup(opts); +- memset(opts, 0, sizeof(opts)); +- } else if (!strcmp($1, "remopts")) { ++ else if (!strcmp($1, "remopts")) + entry.remopts = amd_strdup(opts); +- memset(opts, 0, sizeof(opts)); +- } else { +- memset(opts, 0, sizeof(opts)); ++ else { + amd_notify($1); + YYABORT; + } diff --git a/SOURCES/autofs-5.1.0-beta1-fix-expire-when-server-not-responding.patch b/SOURCES/autofs-5.1.0-beta1-fix-expire-when-server-not-responding.patch new file mode 100644 index 0000000..be62b2a --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-expire-when-server-not-responding.patch @@ -0,0 +1,50 @@ +autofs-5.1.0-beta1 - fix expire when server not responding + +From: Ian Kent + +The change to handle expire of symlinks relies on doing a stat(2) +call to check if the path to be expired is a symlink. + +But system calls that invoke a path walk on real mounts need to be +avoided during expire because if the server isn't responding they +will hang. +--- + CHANGELOG | 1 + + daemon/automount.c | 7 ++++++- + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -117,6 +117,7 @@ + - fix incorrect max key length in defaults get_hash(). + - fix xfn sets incorrect lexer state. + - fix old style key lookup. ++- fix expire when server not responding. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/automount.c ++++ autofs-5.0.7/daemon/automount.c +@@ -573,9 +573,13 @@ int umount_multi(struct autofs_point *ap + + debug(ap->logopt, "path %s incl %d", path, incl); + ++ /* If path is a mount it can't be a symlink */ ++ if (is_mounted(_PATH_MOUNTED, path, MNTS_ALL)) ++ goto real_mount; ++ + if (lstat(path, &st)) { + warn(ap->logopt, +- "failed to stat mount point directory %s", path); ++ "failed to stat directory or symlink %s", path); + return 1; + } + +@@ -617,6 +621,7 @@ int umount_multi(struct autofs_point *ap + return 0; + } + ++real_mount: + is_autofs_fs = 0; + if (master_find_submount(ap, path)) + is_autofs_fs = 1; diff --git a/SOURCES/autofs-5.1.0-beta1-fix-hash-on-config-option-add-and-delete.patch b/SOURCES/autofs-5.1.0-beta1-fix-hash-on-config-option-add-and-delete.patch new file mode 100644 index 0000000..789cb93 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-hash-on-config-option-add-and-delete.patch @@ -0,0 +1,107 @@ +autofs-5.1.0-beta1 - fix hash on confg option add and delete + +From: Ian Kent + +The hash calculation needs to be the same for upper and lower case config +options. The config entry add and delete functions weren't doing that. +--- + CHANGELOG | 1 + + lib/defaults.c | 40 ++++++++++++++++++++++------------------ + 2 files changed, 23 insertions(+), 18 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -120,6 +120,7 @@ + - fix expire when server not responding. + - fix ldap_uri config update. + - fix typo in conf_load_autofs_defaults(). ++- fix hash on confg option add and delete. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -524,12 +524,24 @@ error: + return 0; + } + ++static u_int32_t get_hash(const char *key, unsigned int size) ++{ ++ const char *pkey = key; ++ char lkey[PATH_MAX + 1]; ++ char *plkey = &lkey[0]; ++ ++ while (*pkey) ++ *plkey++ = tolower(*pkey++); ++ *plkey = '\0'; ++ return hash(lkey, size); ++} ++ + static int conf_add(const char *section, const char *key, const char *value, unsigned long flags) + { + struct conf_option *co; + char *sec, *name, *val, *tmp; + unsigned int size = CFG_TABLE_SIZE; +- u_int32_t index; ++ u_int32_t key_hash; + int ret = CFG_FAIL; + + sec = name = val = tmp = NULL; +@@ -568,12 +580,12 @@ static int conf_add(const char *section, + if (flags & CONF_ENV && value) + setenv(name, value, 0); + +- index = hash(key, size); +- if (!config->hash[index]) +- config->hash[index] = co; ++ key_hash = get_hash(key, size); ++ if (!config->hash[key_hash]) ++ config->hash[key_hash] = co; + else { + struct conf_option *last = NULL, *next; +- next = config->hash[index]; ++ next = config->hash[key_hash]; + while (next) { + last = next; + next = last->next; +@@ -598,9 +610,11 @@ static void conf_delete(const char *sect + { + struct conf_option *co, *last; + unsigned int size = CFG_TABLE_SIZE; ++ u_int32_t key_hash; + + last = NULL; +- for (co = config->hash[hash(key, size)]; co != NULL; co = co->next) { ++ key_hash = get_hash(key, size); ++ for (co = config->hash[key_hash]; co != NULL; co = co->next) { + if (strcasecmp(section, co->section)) + continue; + if (!strcasecmp(key, co->name)) +@@ -613,6 +627,8 @@ static void conf_delete(const char *sect + + if (last) + last->next = co->next; ++ else ++ config->hash[key_hash] = co->next; + + free(co->section); + free(co->name); +@@ -661,18 +677,6 @@ error: + return ret; + } + +-static u_int32_t get_hash(const char *key, unsigned int size) +-{ +- const char *pkey = key; +- char lkey[PATH_MAX + 1]; +- char *plkey = &lkey[0]; +- +- while (*pkey) +- *plkey++ = tolower(*pkey++); +- *plkey = '\0'; +- return hash(lkey, size); +-} +- + static struct conf_option *conf_lookup_key(const char *section, const char *key) + { + struct conf_option *co; diff --git a/SOURCES/autofs-5.1.0-beta1-fix-incorrect-max-key-length-in-defaults-get_hash.patch b/SOURCES/autofs-5.1.0-beta1-fix-incorrect-max-key-length-in-defaults-get_hash.patch new file mode 100644 index 0000000..4ef58d2 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-incorrect-max-key-length-in-defaults-get_hash.patch @@ -0,0 +1,49 @@ +autofs-5.1.0-beta1 - fix incorrect max key length in defaults get_hash() + +From: Ian Kent + +amd section names can correspond to mount point path names. +--- + CHANGELOG | 1 + + lib/defaults.c | 6 ++++-- + 2 files changed, 5 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -114,6 +114,7 @@ + - fix ldap default schema config. + - fix ldap default master map name config. + - fix map format init in lookup_init(). ++- fix incorrect max key length in defaults get_hash(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -43,7 +43,6 @@ + #define OLD_CONFIG_FILE AUTOFS_CONF_DIR "/autofs" + #define MAX_LINE_LEN 256 + #define MAX_SECTION_NAME MAX_LINE_LEN +-#define MAX_CFG_NAME_LEN 31 + + #define NAME_MASTER_MAP "master_map_name" + +@@ -665,7 +664,7 @@ error: + static u_int32_t get_hash(const char *key, unsigned int size) + { + const char *pkey = key; +- char lkey[MAX_CFG_NAME_LEN]; ++ char lkey[PATH_MAX + 1]; + char *plkey = &lkey[0]; + + while (*pkey) +@@ -683,6 +682,9 @@ static struct conf_option *conf_lookup(c + if (!key || !section) + return NULL; + ++ if (strlen(key) > PATH_MAX) ++ return NULL; ++ + key_hash = get_hash(key, size); + for (co = config->hash[key_hash]; co != NULL; co = co->next) { + if (strcasecmp(section, co->section)) diff --git a/SOURCES/autofs-5.1.0-beta1-fix-ldap-default-master-map-name-config.patch b/SOURCES/autofs-5.1.0-beta1-fix-ldap-default-master-map-name-config.patch new file mode 100644 index 0000000..206e2b7 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-ldap-default-master-map-name-config.patch @@ -0,0 +1,38 @@ +autofs-5.1.0-beta1 - fix ldap default master map name config + +From: Ian Kent + +If there is no master map name defined in the autofs configuration the +lookup will try to find a map with the default name and if the map isn't +found will substute dots with underscores and repeat the lookup. + +So don't set the default master map name at defaults initialization time. +--- + CHANGELOG | 1 + + lib/defaults.c | 5 ----- + 2 files changed, 1 insertion(+), 5 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -112,6 +112,7 @@ + - fix wildcard key lookup. + - fix out of order amd timestamp lookup. + - fix ldap default schema config. ++- fix ldap default master map name config. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -266,11 +266,6 @@ static int conf_load_autofs_defaults(voi + const char *sec = autofs_gbl_sec; + int ret; + +- ret = conf_update(sec, NAME_MASTER_MAP, +- DEFAULT_MASTER_MAP_NAME, CONF_ENV); +- if (ret == CFG_FAIL) +- goto error; +- + ret = conf_update(sec, NAME_TIMEOUT, + DEFAULT_TIMEOUT, CONF_ENV); + if (ret == CFG_FAIL) diff --git a/SOURCES/autofs-5.1.0-beta1-fix-ldap-default-schema-config.patch b/SOURCES/autofs-5.1.0-beta1-fix-ldap-default-schema-config.patch new file mode 100644 index 0000000..41b1589 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-ldap-default-schema-config.patch @@ -0,0 +1,58 @@ +autofs-5.1.0-beta1 - fix ldap default schema config + +From: Ian Kent + +If there is no schema set in the autofs configuration then the ldap +lookup module assumes it will get a NULL return when it asks for the +default schema. + +So don't set the default schema at defaults initialization time. +--- + CHANGELOG | 1 + + lib/defaults.c | 25 ------------------------- + 2 files changed, 1 insertion(+), 25 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -111,6 +111,7 @@ + - add amd map format parser. + - fix wildcard key lookup. + - fix out of order amd timestamp lookup. ++- fix ldap default schema config. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -301,31 +301,6 @@ static int conf_load_autofs_defaults(voi + if (ret == CFG_FAIL) + goto error; + +- ret = conf_update(sec, NAME_MAP_OBJ_CLASS, +- DEFAULT_MAP_OBJ_CLASS, CONF_ENV); +- if (ret == CFG_FAIL) +- goto error; +- +- ret = conf_update(sec, NAME_ENTRY_OBJ_CLASS, +- DEFAULT_ENTRY_OBJ_CLASS, CONF_ENV); +- if (ret == CFG_FAIL) +- goto error; +- +- ret = conf_update(sec, NAME_MAP_ATTR, +- DEFAULT_MAP_ATTR, CONF_ENV); +- if (ret == CFG_FAIL) +- goto error; +- +- ret = conf_update(sec, NAME_ENTRY_ATTR, +- DEFAULT_ENTRY_ATTR, CONF_ENV); +- if (ret == CFG_FAIL) +- goto error; +- +- ret = conf_update(sec, NAME_VALUE_ATTR, +- DEFAULT_VALUE_ATTR, CONF_ENV); +- if (ret == CFG_FAIL) +- goto error; +- + ret = conf_update(sec, NAME_APPEND_OPTIONS, + DEFAULT_APPEND_OPTIONS, CONF_ENV); + if (ret == CFG_FAIL) diff --git a/SOURCES/autofs-5.1.0-beta1-fix-ldap_uri-config-update.patch b/SOURCES/autofs-5.1.0-beta1-fix-ldap_uri-config-update.patch new file mode 100644 index 0000000..6809a17 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-ldap_uri-config-update.patch @@ -0,0 +1,60 @@ +autofs-5.1.0-beta1 - fix ldap_uri config update + +From: Ian Kent + +Fix some errors in ldap get uris and get search dns. +--- + CHANGELOG | 1 + + lib/defaults.c | 11 +++++------ + 2 files changed, 6 insertions(+), 6 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -118,6 +118,7 @@ + - fix xfn sets incorrect lexer state. + - fix old style key lookup. + - fix expire when server not responding. ++- fix ldap_uri config update. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -1100,19 +1100,18 @@ struct list_head *defaults_get_uris(void + struct list_head *list; + + list = malloc(sizeof(struct list_head)); +- if (!list) { ++ if (!list) + return NULL; +- } + INIT_LIST_HEAD(list); + +- if (defaults_read_config(0)) { ++ if (!defaults_read_config(0)) { + free(list); + return NULL; + } + + pthread_mutex_lock(&conf_mutex); + co = conf_lookup(autofs_gbl_sec, NAME_LDAP_URI); +- if (!co || !co->value) { ++ if (!co) { + pthread_mutex_unlock(&conf_mutex); + free(list); + return NULL; +@@ -1233,12 +1232,12 @@ struct ldap_searchdn *defaults_get_searc + struct conf_option *co; + struct ldap_searchdn *sdn, *last; + +- if (defaults_read_config(0)) ++ if (!defaults_read_config(0)) + return NULL; + + pthread_mutex_lock(&conf_mutex); + co = conf_lookup(autofs_gbl_sec, NAME_SEARCH_BASE); +- if (!co || !co->value) { ++ if (!co) { + pthread_mutex_unlock(&conf_mutex); + return NULL; + } diff --git a/SOURCES/autofs-5.1.0-beta1-fix-map-format-init-in-lookup_init.patch b/SOURCES/autofs-5.1.0-beta1-fix-map-format-init-in-lookup_init.patch new file mode 100644 index 0000000..001dbc4 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-map-format-init-in-lookup_init.patch @@ -0,0 +1,32 @@ +autofs-5.1.0-beta1 - fix map format init in lookup_init() + +From: Ian Kent + +is_format_amd is not initialized in modules/lookup_ldap.c:lookup_init() +which can cause it to be incorrect leading to a failure to locate a +base dn. +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 1 + + 2 files changed, 2 insertions(+) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -113,6 +113,7 @@ + - fix out of order amd timestamp lookup. + - fix ldap default schema config. + - fix ldap default master map name config. ++- fix map format init in lookup_init(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -1647,6 +1647,7 @@ int lookup_init(const char *mapfmt, int + /* If a map type isn't explicitly given, parse it like sun entries. */ + if (mapfmt == NULL) + mapfmt = MAPFMT_DEFAULT; ++ is_amd_format = 0; + if (!strcmp(mapfmt, "amd")) { + is_amd_format = 1; + ctxt->format = MAP_FLAG_FORMAT_AMD; diff --git a/SOURCES/autofs-5.1.0-beta1-fix-multi-entry-ldap-option-handling.patch b/SOURCES/autofs-5.1.0-beta1-fix-multi-entry-ldap-option-handling.patch new file mode 100644 index 0000000..f38999c --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-multi-entry-ldap-option-handling.patch @@ -0,0 +1,310 @@ +autofs-5.1.0-beta1 - fix multi entry ldap option handling + +From: Ian Kent + +Handling new and old configurations presents special problems for +configuration entries that may have repeated values, such as ldap_uris +and ldap_search_base, which can be overridden when the old configuration +is read. + +If entries exist in the new configuration they need to be saved and +restored if there's no entries in the old configuration or, if entries +exist in the old configuration, they need to be discarded. +--- + CHANGELOG | 1 + lib/defaults.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++----------- + 2 files changed, 198 insertions(+), 44 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -122,6 +122,7 @@ + - fix typo in conf_load_autofs_defaults(). + - fix hash on confg option add and delete. + - add plus to path match pattern. ++- fix multi entry ldap option handling. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -916,83 +916,236 @@ static int read_config(unsigned int to_s + return 0; + } + +-/* +- * Read config env variables and check they have been set. +- * +- * This simple minded routine assumes the config file +- * is valid bourne shell script without spaces around "=" +- * and that it has valid values. +- */ +-unsigned int defaults_read_config(unsigned int to_syslog) ++struct conf_option *save_ldap_option_list(const char *key) + { +- FILE *f; +- struct stat stb; +- int ret; ++ struct conf_option *co, *head, *this, *last; ++ unsigned int size = CFG_TABLE_SIZE; ++ u_int32_t key_hash; ++ ++ key_hash = get_hash(key, size); ++ co = config->hash[key_hash]; ++ if (!co) ++ return NULL; ++ last = co; ++ ++ head = this = NULL; ++ while (co) { ++ if (strcasecmp(autofs_gbl_sec, co->section)) { ++ last = co; ++ goto next; ++ } + +- pthread_mutex_lock(&conf_mutex); +- if (!config) { +- if (conf_init()) { +- pthread_mutex_unlock(&conf_mutex); +- message(to_syslog, "failed to init config"); +- return 0; ++ if (!strcasecmp(co->name, key)) { ++ /* Unlink from old */ ++ if (co == config->hash[key_hash]) ++ config->hash[key_hash] = co->next; ++ else ++ last->next = co->next; ++ last = co->next; ++ co->next = NULL; ++ /* Add to new */ ++ if (this) ++ this->next = co; ++ this = co; ++ /* If none have been found yet */ ++ if (!head) ++ head = co; ++ co = last; ++ continue; + } ++next: ++ co = co->next; ++ } ++ ++ return head; ++} ++ ++void restore_ldap_option_list(struct conf_option *list) ++{ ++ struct conf_option *co, *this, *last; ++ unsigned int size = CFG_TABLE_SIZE; ++ u_int32_t key_hash; ++ ++ if (!list) ++ return; ++ ++ this = list; ++ while (this) { ++ last = this; ++ this = this->next; ++ } ++ ++ key_hash = get_hash(list->name, size); ++ co = config->hash[key_hash]; ++ config->hash[key_hash] = list; ++ if (co) ++ last->next = co; ++ ++ return; ++} ++ ++void free_ldap_option_list(struct conf_option *list) ++{ ++ struct conf_option *next, *this; ++ ++ if (!list) ++ return; ++ ++ this = list; ++ while (this) { ++ next = this->next; ++ free(this->section); ++ free(this->name); ++ free(this->value); ++ free(this); ++ this = next; + } + +- /* Set configuration to defaults */ ++ return; ++} ++ ++static void clean_ldap_multi_option(const char *key) ++{ ++ const char *sec = autofs_gbl_sec; ++ struct conf_option *co; ++ ++ while ((co = conf_lookup(sec, key))) ++ conf_delete(co->section, co->name); ++ ++ return; ++} ++ ++static int reset_defaults(unsigned int to_syslog) ++{ ++ int ret; ++ + ret = conf_load_autofs_defaults(); + if (!ret) { +- pthread_mutex_unlock(&conf_mutex); + message(to_syslog, "failed to reset autofs default config"); + return 0; + } + + ret = conf_load_amd_defaults(); + if (!ret) { +- pthread_mutex_unlock(&conf_mutex); + message(to_syslog, "failed to reset amd default config"); + return 0; + } + +- f = open_fopen_r(DEFAULT_CONFIG_FILE); +- if (!f) { ++ return 1; ++} ++ ++/* ++ * Read config env variables and check they have been set. ++ * ++ * This simple minded routine assumes the config file ++ * is valid bourne shell script without spaces around "=" ++ * and that it has valid values. ++ */ ++unsigned int defaults_read_config(unsigned int to_syslog) ++{ ++ FILE *conf, *oldconf; ++ struct stat stb, oldstb; ++ int ret, stat, oldstat; ++ ++ ret = 1; ++ ++ pthread_mutex_lock(&conf_mutex); ++ if (!config) { ++ if (conf_init()) { ++ message(to_syslog, "failed to init config"); ++ ret = 0; ++ goto out; ++ } ++ } ++ ++ conf = open_fopen_r(DEFAULT_CONFIG_FILE); ++ if (!conf) + message(to_syslog, "failed to to open config %s", + DEFAULT_CONFIG_FILE); ++ ++ oldconf = open_fopen_r(OLD_CONFIG_FILE); ++ if (!oldconf) ++ message(to_syslog, "failed to to open old config %s", ++ OLD_CONFIG_FILE); ++ ++ /* Neither config has been updated */ ++ stat = oldstat = -1; ++ if (conf && oldconf && ++ (stat = fstat(fileno(conf), &stb) != -1) && ++ stb.st_mtime <= config->modified && ++ (oldstat = fstat(fileno(oldconf), &oldstb) == -1) && ++ oldstb.st_mtime <= config->modified) { ++ fclose(conf); ++ fclose(oldconf); + goto out; + } + +- if (fstat(fileno(f), &stb) != -1) { +- /* Config hasn't been updated */ +- if (stb.st_mtime <= config->modified) { +- fclose(f); ++ if (conf || oldconf) { ++ if (!reset_defaults(to_syslog)) { ++ fclose(conf); ++ fclose(oldconf); ++ ret = 0; + goto out; + } + } + +- ret = read_config(to_syslog, f, DEFAULT_CONFIG_FILE); +- +- if (fstat(fileno(f), &stb) != -1) +- config->modified = stb.st_mtime; +- else +- message(to_syslog, "failed to update config modified time"); ++ /* Update last modified */ ++ if (stat != -1) { ++ if (oldstat == -1) ++ config->modified = stb.st_mtime; ++ else { ++ if (oldstb.st_mtime < stb.st_mtime) ++ config->modified = oldstb.st_mtime; ++ else ++ config->modified = stb.st_mtime; ++ } ++ } + +- fclose(f); ++ if (conf) { ++ read_config(to_syslog, conf, DEFAULT_CONFIG_FILE); ++ fclose(conf); ++ } + + /* +- * Try to read the old config file and override the installed +- * defaults in case user has a stale config following updating +- * to the new config file location. ++ * Read the old config file and override the installed ++ * defaults in case user has a stale config following ++ * updating to the new config file location. + */ ++ if (oldconf) { ++ struct conf_option *ldap_search_base, *ldap_uris; ++ const char *sec = amd_gbl_sec; ++ struct conf_option *co; ++ ++ ldap_search_base = save_ldap_option_list(NAME_SEARCH_BASE); ++ if (ldap_search_base) ++ clean_ldap_multi_option(NAME_SEARCH_BASE); ++ ++ ldap_uris = save_ldap_option_list(NAME_LDAP_URI); ++ if (ldap_uris) ++ clean_ldap_multi_option(NAME_LDAP_URI); ++ ++ read_config(to_syslog, oldconf, OLD_CONFIG_FILE); ++ fclose(oldconf); ++ ++ if (ldap_search_base) { ++ co = conf_lookup(sec, NAME_SEARCH_BASE); ++ if (co) ++ free_ldap_option_list(ldap_search_base); ++ else ++ restore_ldap_option_list(ldap_search_base); ++ } + +- f = open_fopen_r(OLD_CONFIG_FILE); +- if (!f) +- goto out; +- +- read_config(to_syslog, f, OLD_CONFIG_FILE); +- +- fclose(f); ++ if (ldap_uris) { ++ co = conf_lookup(sec, NAME_LDAP_URI); ++ if (co) ++ free_ldap_option_list(ldap_uris); ++ else ++ restore_ldap_option_list(ldap_uris); ++ } ++ } + out: + pthread_mutex_unlock(&conf_mutex); +- return 1; ++ return ret; + } + + static char *conf_get_string(const char *section, const char *name) diff --git a/SOURCES/autofs-5.1.0-beta1-fix-old-style-key-lookup.patch b/SOURCES/autofs-5.1.0-beta1-fix-old-style-key-lookup.patch new file mode 100644 index 0000000..96b1306 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-old-style-key-lookup.patch @@ -0,0 +1,83 @@ +autofs-5.1.0-beta1 - fix old style key lookup + +From: Ian Kent + +Old (old) style configuration keys all started with DEFAULT_ but +the configuration entry lookup requires the has of the lower case +name. So trying to these old style names failes because thet don't +has to the same value. + +So change the key lookup to strip the DEFAULT_ string and retry +the lookup so valid entries hash properly. +--- + CHANGELOG | 1 + + lib/defaults.c | 33 +++++++++++++++++++++------------ + 2 files changed, 22 insertions(+), 12 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -116,6 +116,7 @@ + - fix map format init in lookup_init(). + - fix incorrect max key length in defaults get_hash(). + - fix xfn sets incorrect lexer state. ++- fix old style key lookup. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -673,33 +673,42 @@ static u_int32_t get_hash(const char *ke + return hash(lkey, size); + } + +-static struct conf_option *conf_lookup(const char *section, const char *key) ++static struct conf_option *conf_lookup_key(const char *section, const char *key) + { + struct conf_option *co; + u_int32_t key_hash; + unsigned int size = CFG_TABLE_SIZE; + +- if (!key || !section) +- return NULL; +- +- if (strlen(key) > PATH_MAX) +- return NULL; +- + key_hash = get_hash(key, size); + for (co = config->hash[key_hash]; co != NULL; co = co->next) { + if (strcasecmp(section, co->section)) + continue; + if (!strcasecmp(key, co->name)) + break; ++ } ++ ++ return co; ++} ++ ++static struct conf_option *conf_lookup(const char *section, const char *key) ++{ ++ struct conf_option *co; ++ ++ if (!key || !section) ++ return NULL; ++ ++ if (strlen(key) > PATH_MAX) ++ return NULL; ++ ++ co = conf_lookup_key(section, key); ++ if (!co) { + /* + * Strip "DEFAULT_" and look for config entry for + * backward compatibility with old style config names. ++ * Perhaps this should be a case sensitive compare? + */ +- if (strlen(key) <= 8) +- continue; +- if (!strncasecmp("DEFAULT_", key, 8) && +- !strcasecmp(key + 8, co->name)) +- break; ++ if (strlen(key) > 8 && !strncasecmp("DEFAULT_", key, 8)) ++ co = conf_lookup_key(section, key + 8); + } + + return co; diff --git a/SOURCES/autofs-5.1.0-beta1-fix-out-of-order-amd-timestamp-lookup.patch b/SOURCES/autofs-5.1.0-beta1-fix-out-of-order-amd-timestamp-lookup.patch new file mode 100644 index 0000000..6670659 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-out-of-order-amd-timestamp-lookup.patch @@ -0,0 +1,58 @@ +autofs-5.1.0-beta1 - fix out of order amd timestamp lookup + +From: Ian Kent + +The call in ->lookup_init() for an ldap source tries to get the amd +ldap entry timestamp whether or not the map is amd format. +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 7 +++++-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -110,6 +110,7 @@ + - extend fix for crash due to thread unsafe use of libldap. + - add amd map format parser. + - fix wildcard key lookup. ++- fix out of order amd timestamp lookup. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -1621,6 +1621,7 @@ static void validate_uris(struct list_he + */ + int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context) + { ++ unsigned int is_amd_format; + struct lookup_context *ctxt; + char buf[MAX_ERR_BUF]; + int ret; +@@ -1647,6 +1648,7 @@ int lookup_init(const char *mapfmt, int + if (mapfmt == NULL) + mapfmt = MAPFMT_DEFAULT; + if (!strcmp(mapfmt, "amd")) { ++ is_amd_format = 1; + ctxt->format = MAP_FLAG_FORMAT_AMD; + ctxt->check_defaults = 1; + } +@@ -1654,7 +1656,7 @@ int lookup_init(const char *mapfmt, int + ctxt->timeout = defaults_get_ldap_timeout(); + ctxt->network_timeout = defaults_get_ldap_network_timeout(); + +- if (!(ctxt->format & MAP_FLAG_FORMAT_AMD)) { ++ if (!is_amd_format) { + /* + * Parse out the server name and base dn, and fill them + * into the proper places in the lookup context structure. +@@ -1746,7 +1748,8 @@ int lookup_init(const char *mapfmt, int + } + #endif + +- ctxt->timestamp = get_amd_timestamp(ctxt); ++ if (is_amd_format) ++ ctxt->timestamp = get_amd_timestamp(ctxt); + + /* Open the parser, if we can. */ + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); diff --git a/SOURCES/autofs-5.1.0-beta1-fix-typo-in-conf_load_autofs_defaults.patch b/SOURCES/autofs-5.1.0-beta1-fix-typo-in-conf_load_autofs_defaults.patch new file mode 100644 index 0000000..4e58ac2 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-typo-in-conf_load_autofs_defaults.patch @@ -0,0 +1,31 @@ +autofs-5.1.0-beta1 - fix typo in conf_load_autofs_defaults() + +From: Ian Kent + + +--- + CHANGELOG | 1 + + lib/defaults.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -119,6 +119,7 @@ + - fix old style key lookup. + - fix expire when server not responding. + - fix ldap_uri config update. ++- fix typo in conf_load_autofs_defaults(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -320,7 +320,7 @@ static int conf_load_autofs_defaults(voi + if (ret == CFG_FAIL) + goto error; + +- /* LDAP_URI nad SEARCH_BASE can occur multiple times */ ++ /* LDAP_URI and SEARCH_BASE can occur multiple times */ + while ((co = conf_lookup(sec, NAME_LDAP_URI))) + conf_delete(co->section, co->name); + diff --git a/SOURCES/autofs-5.1.0-beta1-fix-wildcard-key-lookup.patch b/SOURCES/autofs-5.1.0-beta1-fix-wildcard-key-lookup.patch new file mode 100644 index 0000000..085dfab --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-wildcard-key-lookup.patch @@ -0,0 +1,160 @@ +autofs-5.1.0-beta1 - fix wildcard key lookup + +From: Ian Kent + +The changes to key matching caused wildcard key lookups for autofs +format maps to fail. +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 10 ++++------ + modules/lookup_nisplus.c | 11 +++++------ + modules/lookup_program.c | 4 ++-- + modules/lookup_yp.c | 6 ++---- + 5 files changed, 14 insertions(+), 18 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -109,6 +109,7 @@ + - fix deadlock in init_ldap_connection. + - extend fix for crash due to thread unsafe use of libldap. + - add amd map format parser. ++- fix wildcard key lookup. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_ldap.c ++++ autofs-5.0.7/modules/lookup_ldap.c +@@ -3349,12 +3349,9 @@ static int match_key(struct autofs_point + else + ret = lookup_one(ap, source, key, key_len, ctxt); + +- if (ret == CHE_OK || ret == CHE_UPDATED) ++ if (ret == CHE_OK || ret == CHE_UPDATED || !is_amd_format) + return ret; + +- if (!is_amd_format) +- return CHE_FAIL; +- + lkp_key = strdup(key); + if (!lkp_key) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +@@ -3399,6 +3396,7 @@ static int check_map_indirect(struct aut + char *key, int key_len, + struct lookup_context *ctxt) + { ++ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; + struct mapent_cache *mc; + struct mapent *me; + time_t now = time(NULL); +@@ -3410,7 +3408,7 @@ static int check_map_indirect(struct aut + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + + pthread_mutex_lock(&ap->entry->current_mutex); +- if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ if (is_amd_format) { + unsigned long timestamp = get_amd_timestamp(ctxt); + if (timestamp > ctxt->timestamp) { + ctxt->timestamp = timestamp; +@@ -3457,7 +3455,7 @@ static int check_map_indirect(struct aut + } + pthread_setcancelstate(cur_state, NULL); + +- if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { ++ if (!is_amd_format) { + /* + * Check for map change and update as needed for + * following cache lookup. +--- autofs-5.0.7.orig/modules/lookup_nisplus.c ++++ autofs-5.0.7/modules/lookup_nisplus.c +@@ -339,6 +339,7 @@ static int match_key(struct autofs_point + const char *key, int key_len, + struct lookup_context *ctxt) + { ++ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; + char buf[MAX_ERR_BUF]; + char *lkp_key; + char *prefix; +@@ -347,12 +348,9 @@ static int match_key(struct autofs_point + ret = lookup_one(ap, source, key, key_len, ctxt); + if (ret < 0) + return ret; +- if (ret == CHE_OK || ret == CHE_UPDATED) ++ if (ret == CHE_OK || ret == CHE_UPDATED || is_amd_format) + return ret; + +- if (!(source->flags & MAP_FLAG_FORMAT_AMD)) +- return CHE_FAIL; +- + lkp_key = strdup(key); + if (!lkp_key) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +@@ -504,6 +502,7 @@ static int check_map_indirect(struct aut + char *key, int key_len, + struct lookup_context *ctxt) + { ++ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; + struct mapent_cache *mc; + struct mapent *me, *exists; + time_t now = time(NULL); +@@ -512,7 +511,7 @@ static int check_map_indirect(struct aut + + mc = source->mc; + +- if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ if (is_amd_format) { + /* Check for a /defaults entry to update the map source */ + if (lookup_amd_defaults(ap, source, ctxt) == CHE_FAIL) { + warn(ap->logopt, MODPREFIX +@@ -559,7 +558,7 @@ static int check_map_indirect(struct aut + } + me = cache_lookup_next(mc, me); + } +- if (source->flags & MAP_FLAG_FORMAT_AMD) ++ if (is_amd_format) + exists = match_cached_key(ap, MODPREFIX, source, key); + else + exists = cache_lookup_distinct(mc, key); +--- autofs-5.0.7.orig/modules/lookup_program.c ++++ autofs-5.0.7/modules/lookup_program.c +@@ -382,7 +382,7 @@ static int match_key(struct autofs_point + char *prefix; + int ret; + +- if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ if (is_amd_format) { + ret = lookup_amd_defaults(ap, source, ctxt); + if (ret != NSS_STATUS_SUCCESS) { + warn(ap->logopt, +@@ -420,7 +420,7 @@ static int match_key(struct autofs_point + ment = lookup_one(ap, lkp_key, lkp_len, ctxt); + if (ment) { + char *start = ment; +- if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ if (is_amd_format) { + start = ment + lkp_len; + while (isblank(*start)) + start++; +--- autofs-5.0.7.orig/modules/lookup_yp.c ++++ autofs-5.0.7/modules/lookup_yp.c +@@ -457,6 +457,7 @@ static int match_key(struct autofs_point + const char *key, int key_len, + struct lookup_context *ctxt) + { ++ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; + char buf[MAX_ERR_BUF]; + char *lkp_key; + char *prefix; +@@ -465,12 +466,9 @@ static int match_key(struct autofs_point + ret = lookup_one(ap, source, key, strlen(key), ctxt); + if (ret < 0) + return ret; +- if (ret == CHE_OK || ret == CHE_UPDATED) ++ if (ret == CHE_OK || ret == CHE_UPDATED || !is_amd_format) + return ret; + +- if (!(source->flags & MAP_FLAG_FORMAT_AMD)) +- return CHE_FAIL; +- + lkp_key = strdup(key); + if (!lkp_key) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); diff --git a/SOURCES/autofs-5.1.0-beta1-fix-xfn-sets-incorrect-lexer-state.patch b/SOURCES/autofs-5.1.0-beta1-fix-xfn-sets-incorrect-lexer-state.patch new file mode 100644 index 0000000..7d4b440 --- /dev/null +++ b/SOURCES/autofs-5.1.0-beta1-fix-xfn-sets-incorrect-lexer-state.patch @@ -0,0 +1,39 @@ +autofs-5.1.0-beta1 - fix xfn sets incorrect lexer state + +From: Ian Kent + +The X/Open Federated Naming service isn't supported and the parser will +call YYABORT() when it sees the MAPXFN token so we must set the start +state to the INITIAL state here for the next yylex() call. +--- + CHANGELOG | 1 + + lib/master_tok.l | 8 +++++++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -115,6 +115,7 @@ + - fix ldap default master map name config. + - fix map format init in lookup_init(). + - fix incorrect max key length in defaults get_hash(). ++- fix xfn sets incorrect lexer state. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/master_tok.l ++++ autofs-5.0.7/lib/master_tok.l +@@ -258,7 +258,13 @@ OPTNTOUT (-n{OPTWS}|-n{OPTWS}={OPTWS}|-- + } + + "-xfn" { +- BEGIN(OPTSTR); ++ /* ++ * The X/Open Federated Naming service isn't supported ++ * and the parser will call YYABORT() when it sees the ++ * MAPXFN token so we must set the start state to the ++ * INITIAL state here for the next yylex() call. ++ */ ++ BEGIN(INITIAL); + strcpy(master_lval.strtype, master_text); + return MAPXFN; + } diff --git a/SOURCES/autofs-5.1.0-check-amd-lex-buffer-len-before-copy.patch b/SOURCES/autofs-5.1.0-check-amd-lex-buffer-len-before-copy.patch new file mode 100644 index 0000000..8f439bf --- /dev/null +++ b/SOURCES/autofs-5.1.0-check-amd-lex-buffer-len-before-copy.patch @@ -0,0 +1,188 @@ +autofs-5.1.0 - check amd lex buffer len before copy + +From: Ian Kent + +Guard against lex to yacc communication buffer overflow. +--- + CHANGELOG | 1 + + modules/amd_tok.l | 49 +++++++++++++++++++++++++++++++------------------ + 2 files changed, 32 insertions(+), 18 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -138,6 +138,7 @@ + - fix buffer size checks in get_network_proximity(). + - fix leak in get_network_proximity(). + - fix buffer size checks in merge_options(). ++- check amd lex buffer len before copy. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/amd_tok.l ++++ autofs-5.0.7/modules/amd_tok.l +@@ -22,6 +22,7 @@ + # undef ECHO + #endif + static void amd_echo(void); /* forward definition */ ++static void amd_copy_buffer(void); + #define ECHO amd_echo() + int amd_wrap(void); + +@@ -125,26 +126,26 @@ CUTSEP (\|\||\/) + + {MAPOPT} { + BEGIN(MAPOPTVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return MAP_OPTION; + + } + + {FSOPTS} { + BEGIN(FSOPTVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return FS_OPTION; + } + + {MNTOPT} { + BEGIN(MNTOPTVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return MNT_OPTION; + } + + {SELOPT} { + BEGIN(SELOPTVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SELECTOR; + } + +@@ -152,13 +153,13 @@ CUTSEP (\|\||\/) + + {SEL1ARG} { + BEGIN(SELARGVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SELECTOR; + } + + {SEL2ARG} { + BEGIN(SELARGVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SELECTOR; + } + +@@ -171,7 +172,7 @@ CUTSEP (\|\||\/) + #.* { return COMMENT; } + + {OTHR} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return OTHER; + } + } +@@ -201,22 +202,22 @@ CUTSEP (\|\||\/) + ":=" { return OPTION_ASSIGN; } + + {FSTYPE} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return FS_TYPE; + } + + {MAPTYPE} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return MAP_TYPE; + } + + {CHEOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return CACHE_OPTION; + } + + {FOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return FS_OPT_VALUE; + } + } +@@ -246,7 +247,7 @@ CUTSEP (\|\||\/) + ":=" { return OPTION_ASSIGN; } + + {FOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return FS_OPT_VALUE; + } + } +@@ -278,7 +279,7 @@ CUTSEP (\|\||\/) + "," { return COMMA; } + + {OPTS} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return OPTION; + } + } +@@ -310,7 +311,7 @@ CUTSEP (\|\||\/) + "!=" { return NOT_EQUAL; } + + {SOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SELECTOR_VALUE; + } + } +@@ -335,24 +336,24 @@ CUTSEP (\|\||\/) + "(" { return LBRACKET; } + + {NOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SEL_ARG_VALUE; + } + + {SOPT}/"," { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SEL_ARG_VALUE; + } + + "," { return COMMA; } + + {SOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SEL_ARG_VALUE; + } + + {FOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SEL_ARG_VALUE; + } + +@@ -368,6 +369,18 @@ int amd_wrap(void) + return 1; + } + ++static void amd_copy_buffer(void) ++{ ++ if (amd_leng < 2048) ++ strcpy(amd_lval.strtype, amd_text); ++ else { ++ strncpy(amd_lval.strtype, amd_text, 2047); ++ amd_lval.strtype[2047] = '\0'; ++ logmsg("warning: truncated option near %s\n", ++ &amd_lval.strtype[2030]); ++ } ++} ++ + static void amd_echo(void) + { + logmsg("%s\n", amd_text); diff --git a/SOURCES/autofs-5.1.0-check-host-macro-is-set-before-use.patch b/SOURCES/autofs-5.1.0-check-host-macro-is-set-before-use.patch new file mode 100644 index 0000000..8e816cf --- /dev/null +++ b/SOURCES/autofs-5.1.0-check-host-macro-is-set-before-use.patch @@ -0,0 +1,34 @@ +autofs-5.1.0 - check host macro is set before use + +From: Ian Kent + +Check marco lookup return for ${host} in match_my_name() before using it. +--- + CHANGELOG | 1 + + modules/parse_amd.c | 5 +++++ + 2 files changed, 6 insertions(+) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -140,6 +140,7 @@ + - fix buffer size checks in merge_options(). + - check amd lex buffer len before copy. + - add return check in ldap check_map_indirect(). ++- check host macro is set before use. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -238,6 +238,11 @@ static int match_my_name(unsigned int lo + return 1; + } + ++ if (!v || !v->val) { ++ error(logopt, "error: ${host} not set"); ++ goto out; ++ } ++ + /* Check if comparison value is an alias */ + + memset(&hints, 0, sizeof(hints)); diff --git a/SOURCES/autofs-5.1.0-check-options-length-before-use-in-parse_amd_c.patch b/SOURCES/autofs-5.1.0-check-options-length-before-use-in-parse_amd_c.patch new file mode 100644 index 0000000..3c3240a --- /dev/null +++ b/SOURCES/autofs-5.1.0-check-options-length-before-use-in-parse_amd_c.patch @@ -0,0 +1,83 @@ +autofs-5.1.0 - check options length before use in parse_amd.c + +From: Ian Kent + +Check for temporary buffer overflow before copy at several places in +modules/parse_amd.c. +--- + CHANGELOG | 1 + + modules/parse_amd.c | 36 ++++++++++++++++++++++++++++++++---- + 2 files changed, 33 insertions(+), 4 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -141,6 +141,7 @@ + - check amd lex buffer len before copy. + - add return check in ldap check_map_indirect(). + - check host macro is set before use. ++- check options length before use in parse_amd.c. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -906,9 +906,20 @@ static int do_auto_mount(struct autofs_p + { + char target[PATH_MAX + 1]; + +- if (!entry->map_type) ++ if (!entry->map_type) { ++ if (strlen(entry->fs) > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: fs option length is too long"); ++ return 0; ++ } + strcpy(target, entry->fs); +- else { ++ } else { ++ if (strlen(entry->fs) + ++ strlen(entry->map_type) + 5 > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: fs + maptype options length is too long"); ++ return 0; ++ } + strcpy(target, entry->map_type); + strcat(target, ",amd:"); + strcat(target, entry->fs); +@@ -925,10 +936,21 @@ static int do_link_mount(struct autofs_p + const char *opts = (entry->opts && *entry->opts) ? entry->opts : NULL; + int ret; + +- if (entry->sublink) ++ if (entry->sublink) { ++ if (strlen(entry->sublink) > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: sublink option length is too long"); ++ return 0; ++ } + strcpy(target, entry->sublink); +- else ++ } else { ++ if (strlen(entry->fs) > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: fs option length is too long"); ++ return 0; ++ } + strcpy(target, entry->fs); ++ } + + if (!(flags & CONF_AUTOFS_USE_LOFS)) + goto symlink; +@@ -1017,6 +1039,12 @@ static int do_nfs_mount(struct autofs_po + unsigned int umount = 0; + int ret = 0; + ++ if (strlen(entry->rhost) + strlen(entry->rfs) + 1 > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: rhost + rfs options length is too long"); ++ return 0; ++ } ++ + strcpy(target, entry->rhost); + strcat(target, ":"); + strcat(target, entry->rfs); diff --git a/SOURCES/autofs-5.1.0-clarify-multiple-mounts-description.patch b/SOURCES/autofs-5.1.0-clarify-multiple-mounts-description.patch new file mode 100644 index 0000000..e34c1b9 --- /dev/null +++ b/SOURCES/autofs-5.1.0-clarify-multiple-mounts-description.patch @@ -0,0 +1,45 @@ +autofs-5.1.0 - clarify multiple mounts description + +From: Ian Kent + +Try and clarify the "Multiple Mounts" and "Replicated Server" sections +in the autofs(5) man page. +--- + CHANGELOG | 1 + + man/autofs.5 | 8 ++++++-- + 2 files changed, 7 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -154,6 +154,7 @@ + - fix out of order clearing of options buffer. + - fix reset amd lexer scan buffer. + - ignore multiple commas in options strings. ++- clarify multiple mounts description. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/man/autofs.5 ++++ autofs-5.0.7/man/autofs.5 +@@ -211,15 +211,19 @@ can be used to name multiple filesystems + .RS +.2i + .ta 1.0i + .nf +-.BI "key [" -options "] [mount-point [" -options "] location...]..." ++.BI "key [ -options ] [[/] location [/relative-mount-point [ -options ] location...]..." + .fi + .RE + .sp + .P + This may extend over multiple lines, quoting the line-breaks with \`\\\'. + If present, the per-mountpoint mount-options are appended to the +-default mount-options. ++default mount-options. This behaviour may be overridden by the append_options ++configuration setting. + .SS Replicated Server ++A mount location can specify multiple hosts for a location, portentially ++with a different export path for the same file system. Historically these ++different locations are read-only and provide the same replicated file system. + .sp + .RS +.2i + .ta 1.5i diff --git a/SOURCES/autofs-5.1.0-dont-allocate-dev_ctl_ops-too-early.patch b/SOURCES/autofs-5.1.0-dont-allocate-dev_ctl_ops-too-early.patch new file mode 100644 index 0000000..ba5b231 --- /dev/null +++ b/SOURCES/autofs-5.1.0-dont-allocate-dev_ctl_ops-too-early.patch @@ -0,0 +1,83 @@ +autofs-5.1.0 - dont allocate dev_ctl_ops too early + +From: Ian Kent + +If the standard io file descriptors have been closed by the cloning +process the file handle for autofs device control can correspond to +a descriptor number of one of the standard io descriptors which will +be closed when the process is daemonized. + +Avoid this by closing the device control descriptor opened when +performing sanity checks at startup so that it can be opened +on a higher numbered file descriptor after the process has switched +to daemon mode. +--- + CHANGELOG | 1 + + lib/mounts.c | 14 +++++++++++++- + 2 files changed, 14 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -127,6 +127,7 @@ + - allow empty value for some map options. + - allow empty value in macro selectors. + - add serialization to sasl init. ++- dont allocate dev_ctl_ops too early. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/mounts.c ++++ autofs-5.0.7/lib/mounts.c +@@ -90,7 +90,7 @@ unsigned int linux_version_code(void) + + unsigned int query_kproto_ver(void) + { +- struct ioctl_ops *ops = get_ioctl_ops(); ++ struct ioctl_ops *ops; + char dir[] = "/tmp/autoXXXXXX", *t_dir; + char options[MAX_OPTIONS_LEN + 1]; + pid_t pgrp = getpgrp(); +@@ -131,10 +131,19 @@ unsigned int query_kproto_ver(void) + return 0; + } + ++ ops = get_ioctl_ops(); ++ if (!ops) { ++ umount(t_dir); ++ close(pipefd[0]); ++ rmdir(t_dir); ++ return 0; ++ } ++ + ops->open(LOGOPT_NONE, &ioctlfd, st.st_dev, t_dir); + if (ioctlfd == -1) { + umount(t_dir); + close(pipefd[0]); ++ close_ioctl_ctl(); + rmdir(t_dir); + return 0; + } +@@ -146,6 +155,7 @@ unsigned int query_kproto_ver(void) + ops->close(LOGOPT_NONE, ioctlfd); + umount(t_dir); + close(pipefd[0]); ++ close_ioctl_ctl(); + rmdir(t_dir); + return 0; + } +@@ -155,6 +165,7 @@ unsigned int query_kproto_ver(void) + ops->close(LOGOPT_NONE, ioctlfd); + umount(t_dir); + close(pipefd[0]); ++ close_ioctl_ctl(); + rmdir(t_dir); + return 0; + } +@@ -162,6 +173,7 @@ unsigned int query_kproto_ver(void) + ops->close(LOGOPT_NONE, ioctlfd); + umount(t_dir); + close(pipefd[0]); ++ close_ioctl_ctl(); + rmdir(t_dir); + + return 1; diff --git a/SOURCES/autofs-5.1.0-fix-FILE-pointer-check-in-defaults_read_config.patch b/SOURCES/autofs-5.1.0-fix-FILE-pointer-check-in-defaults_read_config.patch new file mode 100644 index 0000000..80dc9fb --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-FILE-pointer-check-in-defaults_read_config.patch @@ -0,0 +1,78 @@ +autofs-5.1.0 - fix FILE pointer check in defaults_read_config() + +From: Ian Kent + +Fix possible use after free usage of FILE pointer in defaults_read_config(). +--- + CHANGELOG | 1 + + lib/defaults.c | 15 +++++++-------- + 2 files changed, 8 insertions(+), 8 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -132,6 +132,7 @@ + - fix race accessing qdn in get_query_dn(). + - fix leak in cache_push_mapent(). + - fix config entry read buffer not checked. ++- fix FILE pointer check in defaults_read_config(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -1055,6 +1055,8 @@ unsigned int defaults_read_config(unsign + + ret = 1; + ++ conf = oldconf = NULL; ++ + pthread_mutex_lock(&conf_mutex); + if (!config) { + if (conf_init()) { +@@ -1081,15 +1083,11 @@ unsigned int defaults_read_config(unsign + stb.st_mtime <= config->modified && + (oldstat = fstat(fileno(oldconf), &oldstb) == -1) && + oldstb.st_mtime <= config->modified) { +- fclose(conf); +- fclose(oldconf); + goto out; + } + + if (conf || oldconf) { + if (!reset_defaults(to_syslog)) { +- fclose(conf); +- fclose(oldconf); + ret = 0; + goto out; + } +@@ -1107,10 +1105,8 @@ unsigned int defaults_read_config(unsign + } + } + +- if (conf) { ++ if (conf) + read_config(to_syslog, conf, DEFAULT_CONFIG_FILE); +- fclose(conf); +- } + + /* + * Read the old config file and override the installed +@@ -1131,7 +1127,6 @@ unsigned int defaults_read_config(unsign + clean_ldap_multi_option(NAME_LDAP_URI); + + read_config(to_syslog, oldconf, OLD_CONFIG_FILE); +- fclose(oldconf); + + if (ldap_search_base) { + co = conf_lookup(sec, NAME_SEARCH_BASE); +@@ -1150,6 +1145,10 @@ unsigned int defaults_read_config(unsign + } + } + out: ++ if (conf) ++ fclose(conf); ++ if (oldconf) ++ fclose(oldconf); + pthread_mutex_unlock(&conf_mutex); + return ret; + } diff --git a/SOURCES/autofs-5.1.0-fix-buffer-size-checks-in-get_network_proximity.patch b/SOURCES/autofs-5.1.0-fix-buffer-size-checks-in-get_network_proximity.patch new file mode 100644 index 0000000..3969a1a --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-buffer-size-checks-in-get_network_proximity.patch @@ -0,0 +1,52 @@ +autofs-5.1.0 - fix buffer size checks in get_network_proximity() + +From: Ian Kent + +Add several buffer size checks in get_network_proximity(). +--- + CHANGELOG | 1 + + lib/parse_subs.c | 8 +++++--- + 2 files changed, 6 insertions(+), 3 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -135,6 +135,7 @@ + - fix FILE pointer check in defaults_read_config(). + - fix memory leak in conf_amd_get_log_options(). + - fix signed comparison in inet_fill_net(). ++- fix buffer size checks in get_network_proximity(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/parse_subs.c ++++ autofs-5.0.7/lib/parse_subs.c +@@ -437,7 +437,7 @@ unsigned int get_network_proximity(const + { + struct addrinfo hints; + struct addrinfo *ni, *this; +- char name_or_num[NI_MAXHOST]; ++ char name_or_num[NI_MAXHOST + 1]; + unsigned int proximity; + char *net; + int ret; +@@ -449,16 +449,18 @@ unsigned int get_network_proximity(const + if (net) + strcpy(name_or_num, net); + else { +- char this[NI_MAXHOST]; ++ char this[NI_MAXHOST + 1]; + char *mask; + ++ if (strlen(name) > NI_MAXHOST) ++ return PROXIMITY_ERROR; + strcpy(this, name); + if ((mask = strchr(this, '/'))) + *mask++ = '\0'; + if (!strchr(this, '.')) + strcpy(name_or_num, this); + else { +- char buf[NI_MAXHOST], *new; ++ char buf[NI_MAXHOST + 1], *new; + new = inet_fill_net(this, buf); + if (!new) + return PROXIMITY_ERROR; diff --git a/SOURCES/autofs-5.1.0-fix-buffer-size-checks-in-merge_options.patch b/SOURCES/autofs-5.1.0-fix-buffer-size-checks-in-merge_options.patch new file mode 100644 index 0000000..d3b01d5 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-buffer-size-checks-in-merge_options.patch @@ -0,0 +1,105 @@ +autofs-5.1.0 - fix buffer size checks in merge_options() + +From: Ian Kent + +Fix some buffer size overflow checks in merge_options(). +--- + CHANGELOG | 1 + + lib/parse_subs.c | 25 +++++++++++++++++++++---- + 2 files changed, 22 insertions(+), 4 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -137,6 +137,7 @@ + - fix signed comparison in inet_fill_net(). + - fix buffer size checks in get_network_proximity(). + - fix leak in get_network_proximity(). ++- fix buffer size checks in merge_options(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/parse_subs.c ++++ autofs-5.0.7/lib/parse_subs.c +@@ -886,11 +886,11 @@ static char *hasopt(const char *str, con + + char *merge_options(const char *opt1, const char *opt2) + { +- char str[MAX_OPTIONS_LEN]; +- char result[MAX_OPTIONS_LEN]; +- char neg[MAX_OPTION_LEN]; ++ char str[MAX_OPTIONS_LEN + 1]; ++ char result[MAX_OPTIONS_LEN + 1]; ++ char neg[MAX_OPTION_LEN + 1]; + char *tok, *ptr = NULL; +- size_t len; ++ size_t resultlen, len; + + if ((!opt1 || !*opt1) && (!opt2 || !*opt2)) + return NULL; +@@ -910,9 +910,12 @@ char *merge_options(const char *opt1, co + if (!strcmp(opt1, opt2)) + return strdup(opt1); + ++ if (strlen(str) > MAX_OPTIONS_LEN) ++ return NULL; + memset(result, 0, sizeof(result)); + strcpy(str, opt1); + ++ resultlen = 0; + tok = strtok_r(str, ",", &ptr); + while (tok) { + const char *this = (const char *) tok; +@@ -920,12 +923,15 @@ char *merge_options(const char *opt1, co + if (eq) { + *eq = '\0'; + if (!hasopt(opt2, this)) { ++ if (resultlen + strlen(this) > MAX_OPTIONS_LEN) ++ return NULL; + *eq = '='; + if (!*result) + strcpy(result, this); + else + strcat(result, this); + strcat(result, ","); ++ resultlen += strlen(this) + 1; + goto next; + } + } +@@ -946,10 +952,14 @@ char *merge_options(const char *opt1, co + goto next; + + if (!strncmp(this, "no", 2)) { ++ if (strlen(this + 2) > MAX_OPTION_LEN) ++ return NULL; + strcpy(neg, this + 2); + if (hasopt(opt2, neg)) + goto next; + } else { ++ if ((strlen(this) + 2) > MAX_OPTION_LEN) ++ return NULL; + strcpy(neg, "no"); + strcat(neg, this); + if (hasopt(opt2, neg)) +@@ -959,15 +969,22 @@ char *merge_options(const char *opt1, co + if (hasopt(opt2, tok)) + goto next; + ++ if (resultlen + strlen(this) + 1 > MAX_OPTIONS_LEN) ++ return NULL; ++ + if (!*result) + strcpy(result, this); + else + strcat(result, this); + strcat(result, ","); ++ resultlen =+ strlen(this) + 1; + next: + tok = strtok_r(NULL, ",", &ptr); + } + ++ if (resultlen + strlen(opt2) > MAX_OPTIONS_LEN) ++ return NULL; ++ + if (!*result) + strcpy(result, opt2); + else diff --git a/SOURCES/autofs-5.1.0-fix-config-entry-read-buffer-not-checked.patch b/SOURCES/autofs-5.1.0-fix-config-entry-read-buffer-not-checked.patch new file mode 100644 index 0000000..fecee6e --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-config-entry-read-buffer-not-checked.patch @@ -0,0 +1,45 @@ +autofs-5.1.0 - fix config entry read buffer not checked + +From: Ian Kent + +Check the length of config file line read in and report truncation +if it was too long. +--- + CHANGELOG | 1 + + lib/defaults.c | 8 +++++++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -131,6 +131,7 @@ + - fix incorrect round robin host detection. + - fix race accessing qdn in get_query_dn(). + - fix leak in cache_push_mapent(). ++- fix config entry read buffer not checked. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -834,7 +834,7 @@ static int parse_line(char *line, char * + + static int read_config(unsigned int to_syslog, FILE *f, const char *name) + { +- char buf[MAX_LINE_LEN]; ++ char buf[MAX_LINE_LEN + 2]; + char secbuf[MAX_SECTION_NAME]; + char *new_sec; + char *res; +@@ -842,6 +842,12 @@ static int read_config(unsigned int to_s + new_sec = NULL; + while ((res = fgets(buf, MAX_LINE_LEN, f))) { + char *sec, *key, *value; ++ ++ if (strlen(res) > MAX_LINE_LEN) { ++ message(to_syslog, "%s was truncated, ignored", res); ++ continue; ++ } ++ + sec = key = value = NULL; + if (!parse_line(res, &sec, &key, &value)) + continue; diff --git a/SOURCES/autofs-5.1.0-fix-copy-and-paste-error-in-dup_defaults_entry.patch b/SOURCES/autofs-5.1.0-fix-copy-and-paste-error-in-dup_defaults_entry.patch new file mode 100644 index 0000000..5f3f644 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-copy-and-paste-error-in-dup_defaults_entry.patch @@ -0,0 +1,31 @@ +autofs-5.1.0 - fix copy and paste error in dup_defaults_entry() + +From: Ian Kent + + +--- + CHANGELOG | 1 + + modules/parse_amd.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -143,6 +143,7 @@ + - check host macro is set before use. + - check options length before use in parse_amd.c. + - fix some out of order evaluations in parse_amd.c. ++- fix copy and paste error in dup_defaults_entry(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -1631,7 +1631,7 @@ static struct amd_entry *dup_defaults_en + entry->rfs = tmp; + } + +- if (defaults->rhost && *defaults->rfs) { ++ if (defaults->rhost && *defaults->rhost) { + tmp = strdup(defaults->rhost); + if (tmp) + entry->rhost = tmp; diff --git a/SOURCES/autofs-5.1.0-fix-fix-master-map-type-check.patch b/SOURCES/autofs-5.1.0-fix-fix-master-map-type-check.patch new file mode 100644 index 0000000..c7a38be --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-fix-master-map-type-check.patch @@ -0,0 +1,38 @@ +autofs-5.1.0 - fix fix master map type check + +From: Ian Kent + +The map type is of the form [,] but the master map type +check for the old style map syntax wasn't allowing for to be +given (see commit 7c104167). + +When fixing this an incorrect length was accidently used when checking +for the "yp" map type which causes it to never match. +--- + CHANGELOG | 1 + + daemon/lookup.c | 4 ++-- + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -156,6 +156,7 @@ + - ignore multiple commas in options strings. + - clarify multiple mounts description. + - update man page autofs(8) for systemd. ++- fix fix master map type check. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -233,8 +233,8 @@ int lookup_nss_read_master(struct master + memset(source, 0, 10); + if ((!strncmp(name, "file", 4) && + (name[4] == ',' || name[4] == ':')) || +- (!strncmp(name, "yp", 3) && +- (name[3] == ',' || name[3] == ':')) || ++ (!strncmp(name, "yp", 2) && ++ (name[2] == ',' || name[2] == ':')) || + (!strncmp(name, "nis", 3) && + (name[3] == ',' || name[3] == ':')) || + (!strncmp(name, "nisplus", 7) && diff --git a/SOURCES/autofs-5.1.0-fix-hosts-map-options-check-in-lookup_amd_instance.patch b/SOURCES/autofs-5.1.0-fix-hosts-map-options-check-in-lookup_amd_instance.patch new file mode 100644 index 0000000..f7f79dc --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-hosts-map-options-check-in-lookup_amd_instance.patch @@ -0,0 +1,32 @@ +autofs-5.1.0 - fix hosts map options check in lookup_amd_instance() + +From: Ian Kent + +Ongoing bug fixes have caused a hosts map source check in lookup_amd_instance() +to be inconsistent and consequently not find the iexpected map source. +--- + CHANGELOG | 1 + + daemon/lookup.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -147,6 +147,7 @@ + - fix leak in parse_mount(). + - add mutex call return check in defaults.c. + - force disable browse mode for amd format maps. ++- fix hosts map options check in lookup_amd_instance(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/daemon/lookup.c ++++ autofs-5.0.7/daemon/lookup.c +@@ -843,7 +843,7 @@ static int lookup_amd_instance(struct au + return NSS_STATUS_UNKNOWN; + } + +- if (entry->opts) { ++ if (entry->opts && *entry->opts) { + argv[0] = entry->opts; + argv[1] = NULL; + pargv = argv; diff --git a/SOURCES/autofs-5.1.0-fix-hosts-map-update-on-reload.patch b/SOURCES/autofs-5.1.0-fix-hosts-map-update-on-reload.patch new file mode 100644 index 0000000..d98b40d --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-hosts-map-update-on-reload.patch @@ -0,0 +1,80 @@ +autofs-5.1.0 - fix hosts map update on reload + +From: Ian Kent + +Commit aedfd5aa - "amd lookup fix host mount naming" introduced a +regression when updating sun format maps. + +The amd host mount type assumes the lookup name is the host name for +the host mount but amd uses ${rhost} for this. + +This introduces the possibility of multiple concurrent mount requests +since constructing a mount tree that isn't under the lookup name can't +take advantage of the kernel queuing of other concurrent lookups while +the mount tree is constructed. + +Consequently multi-mount updates (currently only done for the internal +hosts map which the amd parser also uses for its hosts map) can't be +allowed for amd mounts. +--- + CHANGELOG | 1 + + modules/parse_sun.c | 37 ++++++++++++++++++++++++++++--------- + 2 files changed, 29 insertions(+), 9 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -158,6 +158,7 @@ + - update man page autofs(8) for systemd. + - fix fix master map type check. + - fix typo in update_hosts_mounts(). ++- fix hosts map update on reload. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/parse_sun.c ++++ autofs-5.0.7/modules/parse_sun.c +@@ -1356,16 +1356,35 @@ int parse_mount(struct autofs_point *ap, + } + + cache_multi_writelock(me); +- /* Someone beat us to it, return success */ +- if (me->multi) { +- free(options); +- cache_multi_unlock(me); +- cache_unlock(mc); +- pthread_setcancelstate(cur_state, NULL); +- return 0; +- } + /* So we know we're the multi-mount root */ +- me->multi = me; ++ if (!me->multi) ++ me->multi = me; ++ else { ++ /* ++ * The amd host mount type assumes the lookup name ++ * is the host name for the host mount but amd uses ++ * ${rhost} for this. ++ * ++ * This introduces the possibility of multiple ++ * concurrent mount requests since constructing a ++ * mount tree that isn't under the lookup name can't ++ * take advantage of the kernel queuing of other ++ * concurrent lookups while the mount tree is ++ * constructed. ++ * ++ * Consequently multi-mount updates (currently only ++ * done for the internal hosts map which the amd ++ * parser also uses for its hosts map) can't be ++ * allowed for amd mounts. ++ */ ++ if (source->flags & MAP_FLAG_FORMAT_AMD) { ++ free(options); ++ cache_multi_unlock(me); ++ cache_unlock(mc); ++ pthread_setcancelstate(cur_state, NULL); ++ return 0; ++ } ++ } + + age = me->age; + diff --git a/SOURCES/autofs-5.1.0-fix-incorrect-round-robin-host-detection.patch b/SOURCES/autofs-5.1.0-fix-incorrect-round-robin-host-detection.patch new file mode 100644 index 0000000..e4cdd34 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-incorrect-round-robin-host-detection.patch @@ -0,0 +1,31 @@ +autofs-5.1.0 - fix incorrect round robin host detection + +From: Ian Kent + + +--- + CHANGELOG | 1 + + modules/replicated.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -128,6 +128,7 @@ + - allow empty value in macro selectors. + - add serialization to sasl init. + - dont allocate dev_ctl_ops too early. ++- fix incorrect round robin host detection. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/replicated.c ++++ autofs-5.0.7/modules/replicated.c +@@ -946,7 +946,7 @@ try_name: + } + + this = ni; +- while (this->ai_next) { ++ while (this) { + if (this->ai_family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *) this->ai_addr; + if (addr->sin_addr.s_addr != INADDR_LOOPBACK) diff --git a/SOURCES/autofs-5.1.0-fix-leak-in-cache_push_mapent.patch b/SOURCES/autofs-5.1.0-fix-leak-in-cache_push_mapent.patch new file mode 100644 index 0000000..c98a961 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-leak-in-cache_push_mapent.patch @@ -0,0 +1,32 @@ +autofs-5.1.0 - fix leak in cache_push_mapent() + +From: Ian Kent + +cache_push_mapent() incorectly sets the cache entry mapent to the old +value which causes a memory leak when the new map entry isn't NULL. +--- + CHANGELOG | 1 + + lib/cache.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -130,6 +130,7 @@ + - dont allocate dev_ctl_ops too early. + - fix incorrect round robin host detection. + - fix race accessing qdn in get_query_dn(). ++- fix leak in cache_push_mapent(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/cache.c ++++ autofs-5.0.7/lib/cache.c +@@ -203,7 +203,7 @@ int cache_push_mapent(struct mapent *me, + + s->mapent = me->mapent; + s->age = me->age; +- me->mapent = mapent; ++ me->mapent = new; + + if (me->stack) + s->next = me->stack; diff --git a/SOURCES/autofs-5.1.0-fix-leak-in-get_network_proximity.patch b/SOURCES/autofs-5.1.0-fix-leak-in-get_network_proximity.patch new file mode 100644 index 0000000..87df882 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-leak-in-get_network_proximity.patch @@ -0,0 +1,35 @@ +autofs-5.1.0 - fix leak in get_network_proximity() + +From: Ian Kent + +Fix variable net not freed after use in get_network_proximity(). +--- + CHANGELOG | 1 + + lib/parse_subs.c | 5 +++-- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -136,6 +136,7 @@ + - fix memory leak in conf_amd_get_log_options(). + - fix signed comparison in inet_fill_net(). + - fix buffer size checks in get_network_proximity(). ++- fix leak in get_network_proximity(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/parse_subs.c ++++ autofs-5.0.7/lib/parse_subs.c +@@ -446,9 +446,10 @@ unsigned int get_network_proximity(const + return PROXIMITY_ERROR; + + net = get_network_number(name); +- if (net) ++ if (net) { + strcpy(name_or_num, net); +- else { ++ free(net); ++ } else { + char this[NI_MAXHOST + 1]; + char *mask; + diff --git a/SOURCES/autofs-5.1.0-fix-leak-in-parse_mount.patch b/SOURCES/autofs-5.1.0-fix-leak-in-parse_mount.patch new file mode 100644 index 0000000..6959316 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-leak-in-parse_mount.patch @@ -0,0 +1,45 @@ +autofs-5.1.0 - fix leak in parse_mount() + +From: Ian Kent + +Fix a potential memory leak of the allocated mount location +in modules/parse_sun.c:parse_mount(). +--- + CHANGELOG | 1 + + modules/parse_sun.c | 8 ++++++-- + 2 files changed, 7 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -144,6 +144,7 @@ + - check options length before use in parse_amd.c. + - fix some out of order evaluations in parse_amd.c. + - fix copy and paste error in dup_defaults_entry(). ++- fix leak in parse_mount(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/parse_sun.c ++++ autofs-5.0.7/modules/parse_sun.c +@@ -1567,7 +1567,10 @@ int parse_mount(struct autofs_point *ap, + */ + if ((strstr(options, "fstype=autofs") && + strstr(options, "hosts"))) { +- loc = NULL; ++ if (loc) { ++ free(loc); ++ loc = NULL; ++ } + loclen = 0; + } else { + loclen = strlen(loc); +@@ -1591,7 +1594,8 @@ int parse_mount(struct autofs_point *ap, + rv = sun_mount(ap, ap->path, name, name_len, + loc, loclen, options, ctxt); + +- free(loc); ++ if (loc) ++ free(loc); + free(options); + pthread_setcancelstate(cur_state, NULL); + } diff --git a/SOURCES/autofs-5.1.0-fix-mem-leak-in-create_client.patch b/SOURCES/autofs-5.1.0-fix-mem-leak-in-create_client.patch new file mode 100644 index 0000000..84cbf99 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-mem-leak-in-create_client.patch @@ -0,0 +1,35 @@ +autofs-5.1.0 - fix memory leak in create_client() + +From: Ian Kent + +In create_client(), if the target host is unreachable the function +exists without freeing the addrinfo data returned from getaddrinfo(3). +--- + CHANGELOG | 1 + + lib/rpc_subs.c | 4 +++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -148,6 +148,7 @@ + - add mutex call return check in defaults.c. + - force disable browse mode for amd format maps. + - fix hosts map options check in lookup_amd_instance(). ++- fix memory leak in create_client(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/rpc_subs.c ++++ autofs-5.0.7/lib/rpc_subs.c +@@ -719,8 +719,10 @@ static int create_client(struct conn_inf + ret = rpc_do_create_client(haddr->ai_addr, info, &fd, client); + if (ret == 0) + break; +- if (ret == -EHOSTUNREACH) ++ if (ret == -EHOSTUNREACH) { ++ freeaddrinfo(ai); + goto out_close; ++ } + + if (!info->client && fd != RPC_ANYSOCK) { + close(fd); diff --git a/SOURCES/autofs-5.1.0-fix-memory-leak-in-conf_amd_get_log_options.patch b/SOURCES/autofs-5.1.0-fix-memory-leak-in-conf_amd_get_log_options.patch new file mode 100644 index 0000000..557f8a9 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-memory-leak-in-conf_amd_get_log_options.patch @@ -0,0 +1,30 @@ +autofs-5.1.0 - fix memory leak in conf_amd_get_log_options() + +From: Ian Kent + +Fix obvious memory leak in conf_amd_get_log_options(). +--- + CHANGELOG | 1 + + lib/defaults.c | 1 + + 2 files changed, 2 insertions(+) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -133,6 +133,7 @@ + - fix leak in cache_push_mapent(). + - fix config entry read buffer not checked. + - fix FILE pointer check in defaults_read_config(). ++- fix memory leak in conf_amd_get_log_options(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/defaults.c ++++ autofs-5.0.7/lib/defaults.c +@@ -1794,6 +1794,7 @@ unsigned int conf_amd_get_log_options(vo + if (log_level < LOG_CRIT) + log_level = LOG_CRIT; + } ++ free(tmp); + } + + if (log_level == -1) diff --git a/SOURCES/autofs-5.1.0-fix-memory-leak-in-get_defaults_entry.patch b/SOURCES/autofs-5.1.0-fix-memory-leak-in-get_defaults_entry.patch new file mode 100644 index 0000000..d4fe877 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-memory-leak-in-get_defaults_entry.patch @@ -0,0 +1,35 @@ +autofs-5.1.0 - fix memory leak in get_defaults_entry() + +From: Ian Kent + +In get_defaults_entry(), if parsing of the expanded defaults string fails +the expanded string used for the parse is not freed. +--- + CHANGELOG | 1 + + modules/parse_amd.c | 4 +++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -150,6 +150,7 @@ + - fix hosts map options check in lookup_amd_instance(). + - fix memory leak in create_client(). + - fix memory leak in get_exports(). ++- fix memory leak in get_defaults_entry(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -1797,8 +1797,10 @@ static struct amd_entry *get_defaults_en + char *expand; + if (!expand_selectors(ap, defaults, &expand, sv)) + goto out; +- if (amd_parse_list(ap, expand, &dflts, &sv)) ++ if (amd_parse_list(ap, expand, &dflts, &sv)) { ++ free(expand); + goto out; ++ } + entry = select_default_entry(ap, &dflts, sv); + if (!entry->map_type) { + /* diff --git a/SOURCES/autofs-5.1.0-fix-memory-leak-in-get_exports.patch b/SOURCES/autofs-5.1.0-fix-memory-leak-in-get_exports.patch new file mode 100644 index 0000000..f1d0516 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-memory-leak-in-get_exports.patch @@ -0,0 +1,81 @@ +autofs-5.1.0 - fix memory leak in get_exports() + +From: Ian Kent + +In modules/lookup_hosts.c:get_exports() looping over the returned list of +exports uses the pointer that contains the list. The pointer is updated +in the process of creating the exports multi-mount so a pointer to the +returned list is no longer available to be freed when done. +--- + CHANGELOG | 1 + + modules/lookup_hosts.c | 17 +++++++++-------- + 2 files changed, 10 insertions(+), 8 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -149,6 +149,7 @@ + - force disable browse mode for amd format maps. + - fix hosts map options check in lookup_amd_instance(). + - fix memory leak in create_client(). ++- fix memory leak in get_exports(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_hosts.c ++++ autofs-5.0.7/modules/lookup_hosts.c +@@ -82,18 +82,19 @@ static char *get_exports(struct autofs_p + { + char buf[MAX_ERR_BUF]; + char *mapent; +- exports exp; ++ exports exp, this; + + debug(ap->logopt, MODPREFIX "fetchng export list for %s", host); + + exp = rpc_get_exports(host, 10, 0, RPC_CLOSE_NOLINGER); + + mapent = NULL; +- while (exp) { ++ this = exp; ++ while (this) { + if (mapent) { + int len = strlen(mapent) + 1; + +- len += strlen(host) + 2*(strlen(exp->ex_dir) + 2) + 3; ++ len += strlen(host) + 2*(strlen(this->ex_dir) + 2) + 3; + mapent = realloc(mapent, len); + if (!mapent) { + char *estr; +@@ -103,10 +104,10 @@ static char *get_exports(struct autofs_p + return NULL; + } + strcat(mapent, " \""); +- strcat(mapent, exp->ex_dir); ++ strcat(mapent, this->ex_dir); + strcat(mapent, "\""); + } else { +- int len = 2*(strlen(exp->ex_dir) + 2) + strlen(host) + 3; ++ int len = 2*(strlen(this->ex_dir) + 2) + strlen(host) + 3; + + mapent = malloc(len); + if (!mapent) { +@@ -117,16 +118,16 @@ static char *get_exports(struct autofs_p + return NULL; + } + strcpy(mapent, "\""); +- strcat(mapent, exp->ex_dir); ++ strcat(mapent, this->ex_dir); + strcat(mapent, "\""); + } + strcat(mapent, " \""); + strcat(mapent, host); + strcat(mapent, ":"); +- strcat(mapent, exp->ex_dir); ++ strcat(mapent, this->ex_dir); + strcat(mapent, "\""); + +- exp = exp->ex_next; ++ this = this->ex_next; + } + rpc_exports_free(exp); + diff --git a/SOURCES/autofs-5.1.0-fix-out-of-order-clearing-of-options-buffer.patch b/SOURCES/autofs-5.1.0-fix-out-of-order-clearing-of-options-buffer.patch new file mode 100644 index 0000000..85da1e7 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-out-of-order-clearing-of-options-buffer.patch @@ -0,0 +1,39 @@ +autofs-5.1.0 - fix out of order clearing of options buffer + +From: Ian Kent + +When setting the result of parsing an options string the options buffer +was being cleared before use. +--- + CHANGELOG | 1 + + modules/amd_parse.y | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -151,6 +151,7 @@ + - fix memory leak in create_client(). + - fix memory leak in get_exports(). + - fix memory leak in get_defaults_entry(). ++- fix out of order clearing of options buffer. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/amd_parse.y ++++ autofs-5.0.7/modules/amd_parse.y +@@ -396,7 +396,6 @@ option_assignment: MAP_OPTION OPTION_ASS + } + | MNT_OPTION OPTION_ASSIGN options + { +- memset(opts, 0, sizeof(opts)); + if (!strcmp($1, "opts")) + entry.opts = amd_strdup(opts); + else if (!strcmp($1, "addopts")) +@@ -407,6 +406,7 @@ option_assignment: MAP_OPTION OPTION_ASS + amd_notify($1); + YYABORT; + } ++ memset(opts, 0, sizeof(opts)); + } + | MNT_OPTION OPTION_ASSIGN + { diff --git a/SOURCES/autofs-5.1.0-fix-reset-amd-lexer-scan-buffer.patch b/SOURCES/autofs-5.1.0-fix-reset-amd-lexer-scan-buffer.patch new file mode 100644 index 0000000..1dcec58 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-reset-amd-lexer-scan-buffer.patch @@ -0,0 +1,225 @@ +autofs-5.1.0 - fix reset amd lexer scan buffer + +From: Ian Kent + +When the amd parser encounters an error often the lexer is left in +a state where a new parse can't be started. Fix this by explicitly +naming our start states and resetting to the proper start state at +buffer initialization on each scan. +--- + CHANGELOG | 1 + modules/amd_tok.l | 59 +++++++++++++++++++++++++++++++--------------------- + modules/parse_amd.c | 3 ++ + 3 files changed, 40 insertions(+), 23 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -152,6 +152,7 @@ + - fix memory leak in get_exports(). + - fix memory leak in get_defaults_entry(). + - fix out of order clearing of options buffer. ++- fix reset amd lexer scan buffer. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/amd_tok.l ++++ autofs-5.0.7/modules/amd_tok.l +@@ -1,4 +1,3 @@ +-%{ + /* ----------------------------------------------------------------------- * + * + * Copyright 2013 Ian Kent +@@ -18,6 +17,12 @@ + * + * ----------------------------------------------------------------------- */ + ++%s START MAPOPTVAL FSOPTVAL MNTOPTVAL SELOPTVAL SELARGVAL ++ ++%{ ++ ++static int reset_start_state = 0; ++ + #ifdef ECHO + # undef ECHO + #endif +@@ -71,8 +76,6 @@ int amd_yyinput(char *, int); + + %option nounput + +-%x MAPOPTVAL FSOPTVAL MNTOPTVAL SELOPTVAL SELARGVAL +- + NL \r?\n + OPTWS [[:blank:]]* + OTHR [^!;:=/|\- \t\r\n#]* +@@ -120,7 +123,14 @@ CUTSEP (\|\||\/) + + %% + +-{ ++%{ ++ if (reset_start_state) { ++ BEGIN START; ++ reset_start_state = 0; ++ } ++%} ++ ++{ + {NL} | + \x00 { } + +@@ -179,23 +189,23 @@ CUTSEP (\|\||\/) + + { + {NL} { +- BEGIN(INITIAL); ++ BEGIN(START); + yyless(1); + } + + \x00 { +- BEGIN(INITIAL); ++ BEGIN(START); + return SEPERATOR; + yyless(1); + } + + ";" { +- BEGIN(INITIAL); ++ BEGIN(START); + return SEPERATOR; + } + + {OPTWS} { +- BEGIN(INITIAL); ++ BEGIN(START); + return SPACE; + } + +@@ -224,23 +234,23 @@ CUTSEP (\|\||\/) + + { + {NL} { +- BEGIN(INITIAL); ++ BEGIN(START); + yyless(1); + } + + \x00 { +- BEGIN(INITIAL); ++ BEGIN(START); + return SEPERATOR; + yyless(1); + } + + ";" { +- BEGIN(INITIAL); ++ BEGIN(START); + return SEPERATOR; + } + + {OPTWS} { +- BEGIN(INITIAL); ++ BEGIN(START); + return SPACE; + } + +@@ -254,23 +264,23 @@ CUTSEP (\|\||\/) + + { + {NL} { +- BEGIN(INITIAL); ++ BEGIN(START); + yyless(1); + } + + \x00 { +- BEGIN(INITIAL); ++ BEGIN(START); + return SEPERATOR; + yyless(1); + } + + ";" { +- BEGIN(INITIAL); ++ BEGIN(START); + return SEPERATOR; + } + + {OPTWS} { +- BEGIN(INITIAL); ++ BEGIN(START); + return SPACE; + } + +@@ -286,23 +296,23 @@ CUTSEP (\|\||\/) + + { + {NL} { +- BEGIN(INITIAL); ++ BEGIN(START); + yyless(1); + } + + \x00 { +- BEGIN(INITIAL); ++ BEGIN(START); + return SEPERATOR; + yyless(1); + } + + ";" { +- BEGIN(INITIAL); ++ BEGIN(START); + return SEPERATOR; + } + + {OPTWS} { +- BEGIN(INITIAL); ++ BEGIN(START); + return SPACE; + } + +@@ -318,18 +328,18 @@ CUTSEP (\|\||\/) + + { + {NL} { +- BEGIN(INITIAL); ++ BEGIN(START); + yyless(1); + } + + \x00 { +- BEGIN(INITIAL); ++ BEGIN(START); + return SEPERATOR; + yyless(1); + } + + ";" { +- BEGIN(INITIAL); ++ BEGIN(START); + return SEPERATOR; + } + +@@ -391,6 +401,9 @@ static void amd_echo(void) + + void amd_set_scan_buffer(const char *buffer) + { ++ YY_FLUSH_BUFFER; ++ reset_start_state = 1; ++ + line = buffer; + line_pos = &line[0]; + /* +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -1798,6 +1798,9 @@ static struct amd_entry *get_defaults_en + if (!expand_selectors(ap, defaults, &expand, sv)) + goto out; + if (amd_parse_list(ap, expand, &dflts, &sv)) { ++ error(ap->logopt, MODPREFIX ++ "failed to parse defaults entry, " ++ "attempting to use internal default"); + free(expand); + goto out; + } diff --git a/SOURCES/autofs-5.1.0-fix-signed-comparison-in-inet_fill_net.patch b/SOURCES/autofs-5.1.0-fix-signed-comparison-in-inet_fill_net.patch new file mode 100644 index 0000000..14dc2b4 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-signed-comparison-in-inet_fill_net.patch @@ -0,0 +1,32 @@ +autofs-5.1.0 - fix signed comparison in inet_fill_net() + +From: Ian Kent + +Fix the less than 0 comparison of an incorrectly declared var in +inet_fill_net(). +--- + CHANGELOG | 1 + + lib/parse_subs.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -134,6 +134,7 @@ + - fix config entry read buffer not checked. + - fix FILE pointer check in defaults_read_config(). + - fix memory leak in conf_amd_get_log_options(). ++- fix signed comparison in inet_fill_net(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/parse_subs.c ++++ autofs-5.0.7/lib/parse_subs.c +@@ -378,7 +378,7 @@ unsigned int get_proximity(struct sockad + static char *inet_fill_net(const char *net_num, char *net) + { + char *np; +- unsigned int dots = 3; ++ int dots = 3; + + if (strlen(net_num) > INET_ADDRSTRLEN) + return NULL; diff --git a/SOURCES/autofs-5.1.0-fix-some-out-of-order-evaluations-in-parse_amd_c.patch b/SOURCES/autofs-5.1.0-fix-some-out-of-order-evaluations-in-parse_amd_c.patch new file mode 100644 index 0000000..ec8def8 --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-some-out-of-order-evaluations-in-parse_amd_c.patch @@ -0,0 +1,103 @@ +autofs-5.1.0 - fix some out of order evaluations in parse_amd.c + +From: Ian Kent + +Fix some check contents before NULL check ordering in modules/parse_amd.c. +--- + CHANGELOG | 1 + + modules/parse_amd.c | 33 ++++++++++++++------------------- + 2 files changed, 15 insertions(+), 19 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -142,6 +142,7 @@ + - add return check in ldap check_map_indirect(). + - check host macro is set before use. + - check options length before use in parse_amd.c. ++- fix some out of order evaluations in parse_amd.c. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/parse_amd.c ++++ autofs-5.0.7/modules/parse_amd.c +@@ -1226,13 +1226,12 @@ static unsigned int validate_auto_option + * left blank the mount must be expected to fail so don't + * report the error. + */ +- if (!*entry->fs) +- return 0; +- else if (!entry->fs) { ++ if (!entry->fs) { + error(logopt, MODPREFIX + "%s: file system not given", entry->type); + return 0; +- } ++ } else if (!*entry->fs) ++ return 0; + return 1; + } + +@@ -1255,13 +1254,12 @@ static unsigned int validate_nfs_options + * expected to fail. + */ + if (!entry->rfs || !*entry->rfs) { +- if (!*entry->rfs) ++ if (entry->rfs && !*entry->rfs) + return 0; + /* Map option fs has been intentionally left blank */ + if (entry->fs && !*entry->fs) + return 0; +- if (entry->fs) +- entry->rfs = strdup(entry->fs); ++ entry->rfs = strdup(entry->fs); + if (!entry->rfs) { + error(logopt, MODPREFIX + "%s: remote file system not given", entry->type); +@@ -1285,24 +1283,22 @@ static unsigned int validate_generic_opt + * expected to fail so don't report the error. + */ + if (fstype != AMD_MOUNT_TYPE_LOFS) { +- if (!*entry->dev) +- return 0; +- else if (!entry->dev) { ++ if (!entry->dev) { + error(logopt, MODPREFIX + "%s: mount device not given", entry->type); + return 0; +- } +- } else { +- if (!*entry->rfs) ++ } else if (!*entry->dev) + return 0; +- else if (!entry->rfs) { ++ } else { ++ if (!entry->rfs) { + /* + * Can't use entry->type as the mount type to reprot + * the error since entry->type == "bind" not "lofs". + */ + error(logopt, "lofs: mount device not given"); + return 0; +- } ++ } else if (!*entry->rfs) ++ return 0; + } + if (entry->sublink && !entry->fs) { + error(logopt, MODPREFIX +@@ -1337,13 +1333,12 @@ static unsigned int validate_host_option + * if it isn't given in the map entry. Don't report an error + * if it has been left empty since it's expected to fail. + */ +- if (!*entry->rhost) +- return 0; +- else if (!entry->rhost) { ++ if (!entry->rhost) { + error(logopt, MODPREFIX + "%s: remote host name not given", entry->type); + return 0; +- } ++ } else if (!*entry->rhost) ++ return 0; + return 1; + } + diff --git a/SOURCES/autofs-5.1.0-fix-typo-in-update_hosts_mounts.patch b/SOURCES/autofs-5.1.0-fix-typo-in-update_hosts_mounts.patch new file mode 100644 index 0000000..67566bf --- /dev/null +++ b/SOURCES/autofs-5.1.0-fix-typo-in-update_hosts_mounts.patch @@ -0,0 +1,31 @@ +autofs-5.1.0 - fix typo in update_hosts_mounts() + +From: Ian Kent + +Correct the stutter in the update exports message. +--- + CHANGELOG | 1 + + modules/lookup_hosts.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -157,6 +157,7 @@ + - clarify multiple mounts description. + - update man page autofs(8) for systemd. + - fix fix master map type check. ++- fix typo in update_hosts_mounts(). + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/lookup_hosts.c ++++ autofs-5.0.7/modules/lookup_hosts.c +@@ -214,7 +214,7 @@ next: + goto cont; + + debug(ap->logopt, MODPREFIX +- "attempt to update exports for exports for %s", me->key); ++ "attempt to update exports for %s", me->key); + + master_source_current_wait(ap->entry); + ap->entry->current = source; diff --git a/SOURCES/autofs-5.1.0-force-disable-browse-mode-for-amd-format-maps.patch b/SOURCES/autofs-5.1.0-force-disable-browse-mode-for-amd-format-maps.patch new file mode 100644 index 0000000..cc83947 --- /dev/null +++ b/SOURCES/autofs-5.1.0-force-disable-browse-mode-for-amd-format-maps.patch @@ -0,0 +1,46 @@ +autofs-5.1.0 - force disable browse mode for amd format maps + +From: Ian Kent + +As in am-utils amd format maps using autofs file system don't support +the browse option and in autofs they don't work properly if it is used. + +This might be implemented later but for now forcefully disable it. +--- + CHANGELOG | 1 + + lib/master_parse.y | 2 ++ + modules/mount_autofs.c | 2 ++ + 3 files changed, 5 insertions(+) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -146,6 +146,7 @@ + - fix copy and paste error in dup_defaults_entry(). + - fix leak in parse_mount(). + - add mutex call return check in defaults.c. ++- force disable browse mode for amd format maps. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/lib/master_parse.y ++++ autofs-5.0.7/lib/master_parse.y +@@ -810,6 +810,8 @@ int master_parse_entry(const char *buffe + logopt = LOGOPT_DEBUG; + else if (loglevel <= LOG_INFO && loglevel > LOG_ERR) + logopt = LOGOPT_VERBOSE; ++ /* amd mounts don't support browse mode */ ++ ghost = 0; + } + + +--- autofs-5.0.7.orig/modules/mount_autofs.c ++++ autofs-5.0.7/modules/mount_autofs.c +@@ -261,6 +261,8 @@ int mount_mount(struct autofs_point *ap, + nap->pref = am_entry->pref; + am_entry->pref = NULL; + } ++ /* amd mounts don't support browse mode */ ++ nap->flags &= ~MOUNT_FLAG_GHOST; + } + + if (handle_mounts_startup_cond_init(&suc)) { diff --git a/SOURCES/autofs-5.1.0-ignore-multiple-commas-in-options-strings.patch b/SOURCES/autofs-5.1.0-ignore-multiple-commas-in-options-strings.patch new file mode 100644 index 0000000..85957ea --- /dev/null +++ b/SOURCES/autofs-5.1.0-ignore-multiple-commas-in-options-strings.patch @@ -0,0 +1,50 @@ +autofs-5.1.0 - ignore multiple commas in options strings + +From: Ian Kent + +When parsing options strings (such as opts, addopts or remopts) the parser +would object to multiple occurrances of the comma character. But this is +probably not a significant problem and the parser should just ignore them. +--- + CHANGELOG | 1 + + modules/amd_parse.y | 4 ++++ + modules/amd_tok.l | 4 ++-- + 3 files changed, 7 insertions(+), 2 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -153,6 +153,7 @@ + - fix memory leak in get_defaults_entry(). + - fix out of order clearing of options buffer. + - fix reset amd lexer scan buffer. ++- ignore multiple commas in options strings. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/modules/amd_parse.y ++++ autofs-5.0.7/modules/amd_parse.y +@@ -465,6 +465,10 @@ options: OPTION + { + prepend_opt(opts, $1); + } ++ | OPTION COMMA ++ { ++ prepend_opt(opts, $1); ++ } + ; + + %% +--- autofs-5.0.7.orig/modules/amd_tok.l ++++ autofs-5.0.7/modules/amd_tok.l +@@ -284,9 +284,9 @@ CUTSEP (\|\||\/) + return SPACE; + } + +- ":=" { return OPTION_ASSIGN; } ++ (:=)(,+)? { return OPTION_ASSIGN; } + +- "," { return COMMA; } ++ ,+ { return COMMA; } + + {OPTS} { + amd_copy_buffer(); diff --git a/SOURCES/autofs-5.1.0-update-man-page-autofs-8-for-systemd.patch b/SOURCES/autofs-5.1.0-update-man-page-autofs-8-for-systemd.patch new file mode 100644 index 0000000..52c626a --- /dev/null +++ b/SOURCES/autofs-5.1.0-update-man-page-autofs-8-for-systemd.patch @@ -0,0 +1,112 @@ +autofs-5.1.0 - update man page autofs(8) for systemd + +From: Ian Kent + +Update the autofs(8) man page to account for systems using systemd. +--- + CHANGELOG | 1 + + man/autofs.8.in | 51 +++++++++++++++++++++++++++++++++++++-------------- + 2 files changed, 38 insertions(+), 14 deletions(-) + +--- autofs-5.0.7.orig/CHANGELOG ++++ autofs-5.0.7/CHANGELOG +@@ -155,6 +155,7 @@ + - fix reset amd lexer scan buffer. + - ignore multiple commas in options strings. + - clarify multiple mounts description. ++- update man page autofs(8) for systemd. + + 25/07/2012 autofs-5.0.7 + ======================= +--- autofs-5.0.7.orig/man/autofs.8.in ++++ autofs-5.0.7/man/autofs.8.in +@@ -1,23 +1,30 @@ + .TH AUTOFS 8 "9 Sep 1997" + .SH NAME +-@@initdir@@/autofs \- Control Script for automounter ++Service control for the automounter + .SH SYNOPSIS ++If a SysV init script system is being used: ++.br + .B @@initdir@@/autofs + .I start|stop|restart|reload|status ++.P ++or if the systemd init system is being used: ++.br ++.B systemctl ++.I start|stop|restart|reload|status ++.B autofs.service + .SH "DESCRIPTION" + .B autofs + controls the operation of the + .BR automount (8) +-daemons running on the Linux system. Usually ++daemon(s) running on the Linux system. Usually + .B autofs + is invoked at system boot time with the + .I start + parameter and at shutdown time with the + .I stop +-parameter. The +-.B autofs +-script can also be manually invoked by the system administrator to shut +-down, restart or reload the automounters. ++parameter. Service control actions can also be manually invoked by ++the system administrator to shut down, restart, reload or obtain ++service status. + .P + .SH "OPERATION" + .B autofs +@@ -31,28 +38,44 @@ will mount and start a thread, with the + manage the mount point. + .P + .B @@initdir@@/autofs reload +-will check the current auto.master map against running daemons. It will kill +-those daemons whose entries have changed and then start daemons for new or +-changed entries. ++or ++.B systemctl autofs.service reload ++will check the current auto.master map against the current automount managed ++mounts. It will terminate those daemons or threads (depending on ++.B autofs ++version) whose entries have been removed, re-read the automount maps for ++entries that have changed and start new daemons or threads for entries ++that have been added. + .P +-If a map is modified then the change will become effective immediately. If +-the ++If an indirect map is modified then the change will become effective immediately. ++If an indirect map uses the ++.B browse ++option, the master map contains direct mount maps or the + .I auto.master + map is modified then the + .B autofs +-script must be rerun to activate the changes. ++service control reload action must be rerun to activate the changes. + .P + .B @@initdir@@/autofs status ++or ++.B systemctl autofs.service status + will display the status of, + .BR automount (8) +-,running or not. ++,running or not. When using the systemd init system the status output includes ++somewhat more information related to the service status. ++.P ++.B systemctl(1) ++has more functions than the actions mentioned here, see ++.B systemctl(1) ++for more information. + .SH "SEE ALSO" + .BR automount (8), + .BR autofs (5), + .BR autofs.conf (5), + .BR auto.master (5). + .BR autofs_ldap_auth.conf (5) ++.BR systemctl(1) + .SH AUTHOR + This manual page was written by Christoph Lameter , + for the Debi GNU/Linux system. Edited by H. Peter Anvin +-. ++ and Ian Kent . diff --git a/SPECS/autofs.spec b/SPECS/autofs.spec index d2a7180..c430a86 100644 --- a/SPECS/autofs.spec +++ b/SPECS/autofs.spec @@ -8,7 +8,7 @@ Summary: A tool for automatically mounting and unmounting filesystems Name: autofs Version: 5.0.7 -Release: 40%{?dist} +Release: 48%{?dist} Epoch: 1 License: GPLv2+ Group: System Environment/Daemons @@ -114,6 +114,165 @@ Patch98: autofs-5.0.8-fix-fix-ipv6-libtirpc-getport.patch Patch99: autofs-5.0.8-get_nfs_info-should-query-portmapper-if-port-is-not-given.patch Patch100: autofs-5.0.8-fix-ipv6-libtirpc-getport-proto-not-set.patch Patch101: autofs-5.0.8-fix-portmap-not-trying-proto-v2.patch +Patch102: autofs-5.0.8-fix-negative-status-being-reset-on-map-read.patch +Patch103: autofs-5.0.9-fix-fix-negative-status-being-reset-on-map-read.patch +Patch104: autofs-5.0.9-check-for-non-existent-negative-entries-in-lookup_ghost.patch +Patch105: autofs-5.0.7-allow-use-of-hosts-map-in-maps.patch +Patch106: autofs-5.0.8-fix-options-compare.patch +Patch107: autofs-5.0.8-fix-fix-options-compare.patch + +# pre-patches for amd parser series. +Patch400: autofs-5.0.8-fix-max-declaration.patch +Patch401: autofs-5.0.7-setup-program-map-env-from-macro-table.patch +Patch402: autofs-5.0.7-add-short-host-name-standard-marco-variable.patch +Patch403: autofs-5.0.8-fix-symlink-fail-message-in-mount_bind-c.patch +Patch404: autofs-5.0.7-add-std-vars-to-program-map-invocation.patch +Patch405: autofs-5.0.8-check-for-existing-offset-mount-before-mounting.patch +Patch406: autofs-5.0.8-remove-macro-debug-prints.patch +Patch407: autofs-5.0.8-fix-cache-readlock-not-taken-on-lookup.patch +Patch408: autofs-5.0.7-fix-compilation-of-lookup_ldap_c-without-sasl.patch +Patch409: autofs-5.0.8-fix-undefined-authtype_requires_creds-err-if-ldap-en.patch +Patch410: autofs-5.0.8-pass-map_source-as-function-paramter-where-possible.patch +Patch411: autofs-5.0.8-check-for-bind-onto-self-in-mount_bind-c.patch +Patch412: autofs-5.0.8-fix-symlink-expire.patch +Patch413: autofs-5.0.8-fix-master-map-type-check.patch +Patch414: autofs-5.0.8-dont-clobber-mapent-for-negative-cache.patch +Patch415: autofs-5.0.7-fix-bad-mkdir-permission-on-create.patch +Patch416: autofs-5.0.8-fix-macro_addvar-and-move-init-to-main-thread.patch +Patch417: autofs-5.0.8-change-walk_tree-to-take-ap.patch +Patch418: autofs-5.0.8-add-negative-cache-lookup-to-hesiod-lookup.patch +Patch419: autofs-5.0.8-fix-external-env-configure.patch +Patch420: autofs-5.0.8-make-autofs-5-consistent-with-auto-master-5.patch +Patch421: autofs-5.0.8-fix-map-source-with-type-lookup.patch +Patch422: autofs-5.0.8-fix-fix-map-source-with-type-lookup.patch +Patch423: autofs-5.0.8-fix-lookup_nss_mount-map-lookup.patch +Patch424: autofs-5.0.8-dont-ignore-null-cache-entries-on-multi-mount-umount.patch +Patch425: autofs-5.0.8-fix-inconsistent-error-returns-in-handle_packet_missing_direct.patch +Patch426: autofs-5.0.8-simple-coverity-fixes.patch +Patch427: autofs-5.0.8-remove-stale-debug-message.patch +Patch428: autofs-5.0.8-fixes-for-samples-auto_master.patch +Patch429: autofs-5.0.8-fix-variable-substitution-description.patch +Patch430: autofs-5.0.8-fix-append-options-description-in-README_v5-release.patch +Patch431: autofs-5.0.9-fix-mistake-in-assignment.patch +Patch432: autofs-5.0.8-use-open-instead-of-access.patch +Patch433: autofs-5.0.7-fix-crash-due-to-thread-unsafe-use-of-libldap.patch +Patch434: autofs-5.0.8-fix-deadlock-in-init-ldap-connection.patch +Patch435: autofs-5.0.8-extend-libldap-serialization.patch + +# amd parser series (set1) +Patch500: autofs-5.0.9-amd-lookup-move-get_proximity-to-parse_subs-c.patch +Patch501: autofs-5.0.9-amd-lookup-use-flags-in-map_source-for-format.patch +Patch502: autofs-5.0.9-amd-lookup-rework-config-handling.patch +Patch503: autofs-5.0.9-amd-lookup-add-conf-handling-for-amd-maps.patch +Patch504: autofs-5.0.9-amd-lookup-split-config-into-init-and-config-settings.patch +Patch505: autofs-5.0.9-amd-lookup-update-man-page-autofs-config-description.patch +Patch506: autofs-5.0.9-amd-lookup-add-amd-config-descriptions-to-config.patch +Patch507: autofs-5.0.9-amd-lookup-fix-lofs-mounting.patch +Patch508: autofs-5.0.9-amd-lookup-add-merge_options-function.patch +Patch509: autofs-5.0.9-amd-lookup-add-expandamdent-function.patch +Patch510: autofs-5.0.9-amd-lookup-add-external-mounts-tracking-functions.patch +Patch511: autofs-5.0.9-amd-lookup-add-amd-global-macro-vars.patch +Patch512: autofs-5.0.9-amd-lookup-add-selector-handling-functions.patch +Patch513: autofs-5.0.9-amd-lookup-add-parse_amd-c.patch +Patch514: autofs-5.0.9-amd-lookup-add-parent-prefix-handling.patch +Patch515: autofs-5.0.9-amd-lookup-add-lookup-vars.patch +Patch516: autofs-5.0.9-amd-lookup-add-selector-handling.patch +Patch517: autofs-5.0.9-amd-lookup-add-cut-handling.patch +Patch518: autofs-5.0.9-amd-lookup-add-handling-of-amd-maps-in-the-master-map.patch +Patch519: autofs-5.0.9-amd-lookup-add-cache-partial-match-functions.patch +Patch520: autofs-5.0.9-amd-lookup-fix-expire-of-amd-nfs-mounts.patch +Patch521: autofs-5.0.9-amd-lookup-add-lofs-ext-and-xfs-fs-types.patch +Patch522: autofs-5.0.9-amd-lookup-add-key-matching-helper-function.patch +Patch523: autofs-5.0.9-amd-lookup-update-lookup-file-to-handle-amd-keys.patch +Patch524: autofs-5.0.9-amd-lookup-update-lookup-yp-to-handle-amd-keys.patch +Patch525: autofs-5.0.9-amd-lookup-update-lookup-program-to-handle-amd-keys.patch +Patch526: autofs-5.0.9-amd-lookup-update-lookup-nisplus-to-handle-amd-keys.patch +Patch527: autofs-5.0.8-amd-lookup-update-lookup-ldap-to-handle-amd-keys.patch +Patch528: autofs-5.0.8-amd-lookup-update-lookup-hesiod-to-handle-amd-keys.patch +Patch529: autofs-5.0.9-amd-lookup-add-handling-of-unhandled-options.patch +Patch530: autofs-5.0.9-amd-lookup-use-config-map_type-if-type-is-not-given.patch +Patch531: autofs-5.0.9-amd-lookup-update-man-pages.patch +Patch532: autofs-5.0.9-amd-lookup-add-remopts-handling.patch +Patch533: autofs-5.0.9-amd-lookup-add-nfsl-and-linkx-fs-types.patch +Patch534: autofs-5.0.9-amd-lookup-add-search_path-handling.patch +Patch535: autofs-5.0.9-amd-lookup-fix-host-mount-lookup.patch +Patch536: autofs-5.0.9-amd-lookup-fix-host-mount-naming.patch +Patch537: autofs-5.0.9-amd-lookup-check-for-required-options-for-mounts.patch +Patch538: autofs-5.0.9-amd-lookup-add-cdfs-fs-type.patch +Patch539: autofs-5.0.9-amd-lookup-dont-umount-admin-mounted-external-mounts.patch +Patch540: autofs-5.0.9-amd-lookup-skip-sss-source-for-amd-lookups.patch +Patch541: autofs-5.0.9-amd-lookup-allow-exec-to-be-used-by-amd-maps-in-master-map.patch +Patch542: autofs-5.0.9-amd-lookup-fix-amd-entry-not-found-at-expire.patch +Patch543: autofs-5.0.9-amd-lookup-fix-prefix-not-set-on-mount-reconnect.patch +Patch544: autofs-5.0.9-amd-lookup-add-REDAME-amd-maps.patch +Patch545: autofs-5.0.9-amd-lookup-fix-autofs_use_lofs-value-in-config.patch +Patch546: autofs-5.0.9-amd-lookup-fix-expire-of-external-mounts.patch +Patch547: autofs-5.0.9-amd-lookup-try-to-use-external-mounts-for-real-mounts.patch +Patch548: autofs-5.0.9-amd-lookup-add-ufs-fs-type.patch +Patch549: autofs-5.0.9-amd-lookup-fix-old-conf-handling.patch +Patch550: autofs-5.0.9-amd-lookup-try-to-use-external-mounts-for-nfs-mounts.patch +Patch551: autofs-5.0.9-amd-lookup-update-changelog.patch + +# amd parser series (set2) +Patch552: autofs-5.1.0-beta1-fix-wildcard-key-lookup.patch +Patch553: autofs-5.1.0-beta1-fix-out-of-order-amd-timestamp-lookup.patch +Patch554: autofs-5.1.0-beta1-fix-ldap-default-schema-config.patch +Patch555: autofs-5.1.0-beta1-fix-ldap-default-master-map-name-config.patch +Patch556: autofs-5.1.0-beta1-fix-map-format-init-in-lookup_init.patch +Patch557: autofs-5.1.0-beta1-fix-incorrect-max-key-length-in-defaults-get_hash.patch +Patch558: autofs-5.1.0-beta1-fix-xfn-sets-incorrect-lexer-state.patch +Patch559: autofs-5.1.0-beta1-fix-old-style-key-lookup.patch +Patch560: autofs-5.1.0-beta1-fix-expire-when-server-not-responding.patch +Patch561: autofs-5.1.0-beta1-fix-ldap_uri-config-update.patch +Patch562: autofs-5.1.0-beta1-fix-typo-in-conf_load_autofs_defaults.patch +Patch563: autofs-5.1.0-beta1-fix-hash-on-config-option-add-and-delete.patch +Patch564: autofs-5.1.0-beta1-add-plus-to-path-match-pattern.patch +Patch565: autofs-5.1.0-beta1-fix-multi-entry-ldap-option-handling.patch +Patch566: autofs-5.1.0-beta1-cleanup-options-in-amd_parse-c.patch +Patch567: autofs-5.1.0-beta1-allow-empty-value-for-some-map-options.patch +Patch568: autofs-5.1.0-beta1-allow-empty-value-in-macro-selectors.patch + +Patch600: autofs-5.1.0-add-serialization-to-sasl-init.patch +Patch601: autofs-5.1.0-dont-allocate-dev_ctl_ops-too-early.patch +Patch602: autofs-5.1.0-fix-incorrect-round-robin-host-detection.patch +Patch603: autofs-5.0.9-fix-race-accessing-qdn-in-get_query_dn.patch + +# Coverity motivated fixes, mainly for the new amd parser code +Patch604: autofs-5.1.0-fix-leak-in-cache_push_mapent.patch +Patch605: autofs-5.1.0-fix-config-entry-read-buffer-not-checked.patch +Patch606: autofs-5.1.0-fix-FILE-pointer-check-in-defaults_read_config.patch +Patch607: autofs-5.1.0-fix-memory-leak-in-conf_amd_get_log_options.patch +Patch608: autofs-5.1.0-fix-signed-comparison-in-inet_fill_net.patch +Patch609: autofs-5.1.0-fix-buffer-size-checks-in-get_network_proximity.patch +Patch610: autofs-5.1.0-fix-leak-in-get_network_proximity.patch +Patch611: autofs-5.1.0-fix-buffer-size-checks-in-merge_options.patch +Patch612: autofs-5.1.0-check-amd-lex-buffer-len-before-copy.patch +Patch613: autofs-5.1.0-add-return-check-in-ldap-check_map_indirect.patch +Patch614: autofs-5.1.0-check-host-macro-is-set-before-use.patch +Patch615: autofs-5.1.0-check-options-length-before-use-in-parse_amd_c.patch +Patch616: autofs-5.1.0-fix-some-out-of-order-evaluations-in-parse_amd_c.patch +Patch617: autofs-5.1.0-fix-copy-and-paste-error-in-dup_defaults_entry.patch +Patch618: autofs-5.1.0-fix-leak-in-parse_mount.patch +Patch619: autofs-5.1.0-add-mutex-call-return-check-in-defaults_c.patch + +# more amd format map fixes +Patch620: autofs-5.1.0-force-disable-browse-mode-for-amd-format-maps.patch +Patch621: autofs-5.1.0-fix-hosts-map-options-check-in-lookup_amd_instance.patch + +Patch622: autofs-5.1.0-fix-mem-leak-in-create_client.patch +Patch623: autofs-5.1.0-fix-memory-leak-in-get_exports.patch + +Patch624: autofs-5.1.0-fix-memory-leak-in-get_defaults_entry.patch +Patch625: autofs-5.1.0-fix-out-of-order-clearing-of-options-buffer.patch +Patch626: autofs-5.1.0-fix-reset-amd-lexer-scan-buffer.patch +Patch627: autofs-5.1.0-ignore-multiple-commas-in-options-strings.patch + +Patch628: autofs-5.1.0-clarify-multiple-mounts-description.patch +Patch629: autofs-5.1.0-update-man-page-autofs-8-for-systemd.patch +Patch630: autofs-5.1.0-fix-fix-master-map-type-check.patch +Patch631: autofs-5.1.0-fix-typo-in-update_hosts_mounts.patch +Patch632: autofs-5.1.0-fix-hosts-map-update-on-reload.patch + Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %if %{with_systemd} BuildRequires: systemd-units @@ -121,7 +280,6 @@ BuildRequires: systemd-units BuildRequires: autoconf, hesiod-devel, openldap-devel, bison, flex, libxml2-devel, cyrus-sasl-devel, openssl-devel module-init-tools util-linux nfs-utils e2fsprogs libtirpc-devel BuildRequires: libsss_autofs Conflicts: cyrus-sasl-lib < 2.1.23-9 -Requires: kernel >= 2.6.17 Requires: bash coreutils sed gawk textutils sh-utils grep module-init-tools /bin/ps %if %{with_systemd} Requires(post): systemd-sysv @@ -272,6 +430,158 @@ echo %{version}-%{release} > .version %patch99 -p1 %patch100 -p1 %patch101 -p1 +%patch102 -p1 +%patch103 -p1 +%patch104 -p1 +%patch105 -p1 +%patch106 -p1 +%patch107 -p1 + +# pre-patches for amd parser series. +%patch400 -p1 +%patch401 -p1 +%patch402 -p1 +%patch403 -p1 +%patch404 -p1 +%patch405 -p1 +%patch406 -p1 +%patch407 -p1 +%patch408 -p1 +%patch409 -p1 +%patch410 -p1 +%patch411 -p1 +%patch412 -p1 +%patch413 -p1 +%patch414 -p1 +%patch415 -p1 +%patch416 -p1 +%patch417 -p1 +%patch418 -p1 +%patch419 -p1 +%patch420 -p1 +%patch421 -p1 +%patch422 -p1 +%patch423 -p1 +%patch424 -p1 +%patch425 -p1 +%patch426 -p1 +%patch427 -p1 +%patch428 -p1 +%patch429 -p1 +%patch430 -p1 +%patch431 -p1 +%patch432 -p1 +%patch433 -p1 +%patch434 -p1 +%patch435 -p1 + +# amd parser series (set1) +%patch500 -p1 +%patch501 -p1 +%patch502 -p1 +%patch503 -p1 +%patch504 -p1 +%patch505 -p1 +%patch506 -p1 +%patch507 -p1 +%patch508 -p1 +%patch509 -p1 +%patch510 -p1 +%patch511 -p1 +%patch512 -p1 +%patch513 -p1 +%patch514 -p1 +%patch515 -p1 +%patch516 -p1 +%patch517 -p1 +%patch518 -p1 +%patch519 -p1 +%patch520 -p1 +%patch521 -p1 +%patch522 -p1 +%patch523 -p1 +%patch524 -p1 +%patch525 -p1 +%patch526 -p1 +%patch527 -p1 +%patch528 -p1 +%patch529 -p1 +%patch530 -p1 +%patch531 -p1 +%patch532 -p1 +%patch533 -p1 +%patch534 -p1 +%patch535 -p1 +%patch536 -p1 +%patch537 -p1 +%patch538 -p1 +%patch539 -p1 +%patch540 -p1 +%patch541 -p1 +%patch542 -p1 +%patch543 -p1 +%patch544 -p1 +%patch545 -p1 +%patch546 -p1 +%patch547 -p1 +%patch548 -p1 +%patch549 -p1 +%patch550 -p1 +%patch551 -p1 + +# amd parser series (set2) +%patch552 -p1 +%patch553 -p1 +%patch554 -p1 +%patch555 -p1 +%patch556 -p1 +%patch557 -p1 +%patch558 -p1 +%patch559 -p1 +%patch560 -p1 +%patch561 -p1 +%patch562 -p1 +%patch563 -p1 +%patch564 -p1 +%patch565 -p1 +%patch566 -p1 +%patch567 -p1 +%patch568 -p1 + +%patch600 -p1 +%patch601 -p1 +%patch602 -p1 +%patch603 -p1 +%patch604 -p1 +%patch605 -p1 +%patch606 -p1 +%patch607 -p1 +%patch608 -p1 +%patch609 -p1 +%patch610 -p1 +%patch611 -p1 +%patch612 -p1 +%patch613 -p1 +%patch614 -p1 +%patch615 -p1 +%patch616 -p1 +%patch617 -p1 +%patch618 -p1 +%patch619 -p1 +%patch620 -p1 +%patch621 -p1 +%patch622 -p1 +%patch623 -p1 +%patch624 -p1 +%patch625 -p1 +%patch626 -p1 +%patch627 -p1 + +%patch628 -p1 +%patch629 -p1 +%patch630 -p1 +%patch631 -p1 +%patch632 -p1 %build LDFLAGS=-Wl,-z,now @@ -304,6 +614,7 @@ install -m 644 redhat/autofs.service $RPM_BUILD_ROOT%{unitdir}/autofs.service install -m 755 redhat/autofs.init $RPM_BUILD_ROOT%{_initrddir}/autofs %define init_file_name /etc/rc.d/init.d/autofs %endif +install -m 644 redhat/autofs.conf $RPM_BUILD_ROOT/etc/autofs.conf install -m 644 redhat/autofs.sysconfig $RPM_BUILD_ROOT/etc/sysconfig/autofs %clean @@ -355,6 +666,7 @@ fi %config(noreplace,missingok) /etc/auto.misc %config(noreplace,missingok) /etc/auto.net %config(noreplace,missingok) /etc/auto.smb +%config(noreplace) /etc/autofs.conf %config(noreplace) /etc/sysconfig/autofs %config(noreplace) /etc/autofs_ldap_auth.conf %{_sbindir}/automount @@ -363,6 +675,65 @@ fi %dir /etc/auto.master.d %changelog +* Fri Dec 19 2014 Ian Kent - 1:5.0.7-48 +- bz1164957 - The default installed autofs.conf doesn't have default nfs + protocol set to 4 + - add missing line to copy RedHat customized config to spec file. +- Resolves: rhbz#1164957 + +* Tue Oct 28 2014 Ian Kent - 1:5.0.7-47 +- bz1156662 - autofs /net maps do not refresh list of shares exported on + the NFS server + - fix typo in update_hosts_mounts(). + - fix hosts map update on reload. +- Resolves: rhbz#1156662 + +* Fri Oct 17 2014 Ian Kent - 1:5.0.7-46 +- bz1153414 - autofs-5.0.5-109 with upgrade to RHEL 6.6 no longer recognizes + +yp: in auto.master + - fix fix master map type check. +- Resolves: rhbz#1153414 + +* Wed Oct 15 2014 Ian Kent - 1:5.0.7-45 +- bz1152862 - autofs shouldn't have kernel as a dependency + - remove an ancient kernel Requires. +- Resolves: rhbz#1152862 + +* Tue Oct 7 2014 Ian Kent - 1:5.0.7-44 +- bz1099800 - man page of /etc/init.d/autofs: /usr/share/man/man8/autofs.8.gz + is not needed in RHEL-7 + - update man page autofs(8) for systemd +- Resolves: rhbz#1099800 + +* Thu Sep 25 2014 Ian Kent - 1:5.0.7-43 +- bz1066772 - Clarify autofs(5) man page sections "Multiple Mounts" and + "Replicated Server" + - clarify multiple mounts description. +- Resolves: rhbz#1066772 + +* Mon Sep 22 2014 Ian Kent - 1:5.0.7-42 +- bz1116184 - RFE: RHEL7: Add am-utils RPM or equivalent am-utils functionality + to other packages + - add amd map format parser. +- bz1132236 - Memory leak in get_exports + - fix memory leak in create_client(). + - fix memory leak in get_exports(). +- bz1135158 - double free or corruption (fasttop) causes abort in ldap_int_tls_destroy + - fix deadlock in init_ldap_connection(). + - extend libldap serialization. +- Resolves: rhbz#1116184 rhbz#1132236 rhbz#1135158 + +* Mon Aug 25 2014 Ian Kent - 1:5.0.7-41 +- bz1094661 - autofs can ghost non-existent map entries given the right timing + - fix negative status being reset on map read. + - fix fix negative status being reset on map read. + - check for non existent negative entries in lookup_ghost(). +- bz1124389 - autofs-5.0.5-88.el6 breaks maps that have a -v in the options + - allow use of hosts map in maps (dependent patch). + - fix options compare. + - fix fix options compare. +- Resolves: rhbz#1094661 rhbz#1124389 + * Wed Feb 19 2014 Ian Kent - 1:5.0.7-40 - bz1063139 - autofs regression test failure. - fix fix ipv6 libtirpc getport.