Blame SOURCES/autofs-5.0.9-amd-lookup-add-expandamdent-function.patch

6bbd11
autofs-5.0.9 - amd lookup add expandamdent() function
6bbd11
6bbd11
From: Ian Kent <raven@themaw.net>
6bbd11
6bbd11
6bbd11
---
6bbd11
 include/parse_subs.h |    2 
6bbd11
 lib/parse_subs.c     |  211 ++++++++++++++++++++++++++++++++++++++++++++++++++
6bbd11
 2 files changed, 213 insertions(+)
6bbd11
6bbd11
diff --git a/include/parse_subs.h b/include/parse_subs.h
6bbd11
index e57cf4a..675411d 100644
6bbd11
--- a/include/parse_subs.h
6bbd11
+++ b/include/parse_subs.h
6bbd11
@@ -42,6 +42,8 @@ char *dequote(const char *, int, unsigned int);
6bbd11
 int span_space(const char *, unsigned int);
6bbd11
 char *sanitize_path(const char *, int, unsigned int, unsigned int);
6bbd11
 char *merge_options(const char *, const char *);
6bbd11
+int expandamdent(const char *, char *, const struct substvar *);
6bbd11
+int expand_selectors(struct autofs_point *, const char *, char **, struct substvar *);
6bbd11
 void free_map_type_info(struct map_type_info *);
6bbd11
 struct map_type_info *parse_map_type_info(const char *);
6bbd11
 
6bbd11
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
6bbd11
index 99075b1..279f40e 100644
6bbd11
--- a/lib/parse_subs.c
6bbd11
+++ b/lib/parse_subs.c
6bbd11
@@ -20,6 +20,7 @@
6bbd11
 #include <ctype.h>
6bbd11
 #include <sys/types.h>
6bbd11
 #include <ifaddrs.h>
6bbd11
+#include <libgen.h>
6bbd11
 #include <net/if.h>
6bbd11
 #include "automount.h"
6bbd11
 
6bbd11
@@ -39,6 +40,11 @@ static int volatile ifc_last_len = 0;
6bbd11
 /* Get numeric value of the n bits starting at position p */
6bbd11
 #define getbits(x, p, n)	((x >> (p + 1 - n)) & ~(~0 << n))
6bbd11
 
6bbd11
+#define EXPAND_LEADING_SLASH	0x0001
6bbd11
+#define EXPAND_TRAILING_SLASH	0x0002
6bbd11
+#define EXPAND_LEADING_DOT	0x0004
6bbd11
+#define EXPAND_TRAILING_DOT	0x0008
6bbd11
+
6bbd11
 struct types {
6bbd11
 	char *type;
6bbd11
 	unsigned int len;
6bbd11
@@ -636,6 +642,211 @@ next:
6bbd11
 	return strdup(result);
6bbd11
 }
6bbd11
 
6bbd11
+static char *expand_slash_or_dot(char *str, unsigned int type)
6bbd11
+{
6bbd11
+	char *val = NULL;
6bbd11
+
6bbd11
+	if (!str)
6bbd11
+		return NULL;
6bbd11
+
6bbd11
+	if (!type)
6bbd11
+		return str;
6bbd11
+
6bbd11
+	if (type & EXPAND_LEADING_SLASH)
6bbd11
+		val = basename(str);
6bbd11
+	else if (type & EXPAND_TRAILING_SLASH)
6bbd11
+		val = dirname(str);
6bbd11
+	else if (type & (EXPAND_LEADING_DOT | EXPAND_TRAILING_DOT)) {
6bbd11
+		char *dot = strchr(str, '.');
6bbd11
+		if (dot)
6bbd11
+			*dot++ = '\0';
6bbd11
+		if (type & EXPAND_LEADING_DOT)
6bbd11
+			val = dot;
6bbd11
+		else
6bbd11
+			val = str;
6bbd11
+	}
6bbd11
+
6bbd11
+	return val;
6bbd11
+}
6bbd11
+
6bbd11
+/*
6bbd11
+ * $-expand an amd-style map entry and return the length of the entry.
6bbd11
+ * If "dst" is NULL, just count the length.
6bbd11
+ */
6bbd11
+/* TODO: how should quoting be handled? */
6bbd11
+int expandamdent(const char *src, char *dst, const struct substvar *svc)
6bbd11
+{
6bbd11
+	unsigned int flags = conf_amd_get_flags(NULL);
6bbd11
+	const struct substvar *sv;
6bbd11
+	const char *o_src = src;
6bbd11
+	int len, l;
6bbd11
+	const char *p;
6bbd11
+	char ch;
6bbd11
+
6bbd11
+	len = 0;
6bbd11
+
6bbd11
+	while ((ch = *src++)) {
6bbd11
+		switch (ch) {
6bbd11
+		case '$':
6bbd11
+			if (*src == '{') {
6bbd11
+				char *start, *end;
6bbd11
+				unsigned int type = 0;
6bbd11
+				p = strchr(++src, '}');
6bbd11
+				if (!p) {
6bbd11
+					/* Ignore rest of string */
6bbd11
+					if (dst)
6bbd11
+						*dst = '\0';
6bbd11
+					return len;
6bbd11
+				}
6bbd11
+				start = (char *) src;
6bbd11
+				if (*src == '/' || *src == '.') {
6bbd11
+					start++;
6bbd11
+					type = EXPAND_LEADING_SLASH;
6bbd11
+					if (*src == '.')
6bbd11
+						type = EXPAND_LEADING_DOT;
6bbd11
+				}
6bbd11
+				end = (char *) p;
6bbd11
+				if (*(p - 1) == '/' || *(p - 1) == '.') {
6bbd11
+					end--;
6bbd11
+					type = EXPAND_TRAILING_SLASH;
6bbd11
+					if (*(p - 1) == '.')
6bbd11
+						type = EXPAND_TRAILING_DOT;
6bbd11
+				}
6bbd11
+				sv = macro_findvar(svc, start, end - start);
6bbd11
+				if (sv) {
6bbd11
+					char *val;
6bbd11
+					char *str = strdup(sv->val);
6bbd11
+					val = expand_slash_or_dot(str, type);
6bbd11
+					if (!val)
6bbd11
+						val = sv->val;
6bbd11
+					l = strlen(val);
6bbd11
+					if (dst) {
6bbd11
+						if (*dst)
6bbd11
+							strcat(dst, val);
6bbd11
+						else
6bbd11
+							strcpy(dst, val);
6bbd11
+						dst += l;
6bbd11
+					}
6bbd11
+					len += l;
6bbd11
+					if (str)
6bbd11
+						free(str);
6bbd11
+				} else {
6bbd11
+					if (dst) {
6bbd11
+						*dst++ = ch;
6bbd11
+						*dst++ = '{';
6bbd11
+						strncat(dst, src, p - src);
6bbd11
+						dst += (p - src);
6bbd11
+						*dst++ = '}';
6bbd11
+					}
6bbd11
+					len += 1 + 1 + (p - src) + 1;
6bbd11
+				}
6bbd11
+				src = p + 1;
6bbd11
+			} else {
6bbd11
+				if (dst)
6bbd11
+					*(dst++) = ch;
6bbd11
+				len++;
6bbd11
+			}
6bbd11
+			break;
6bbd11
+
6bbd11
+		case '\\':
6bbd11
+			if (!(flags & CONF_NORMALIZE_SLASHES)) {
6bbd11
+				len++;
6bbd11
+				if (dst)
6bbd11
+					*dst++ = ch;
6bbd11
+				break;
6bbd11
+			}
6bbd11
+
6bbd11
+			if (*src) {
6bbd11
+				len++;
6bbd11
+				if (dst)
6bbd11
+					*dst++ = *src;
6bbd11
+				src++;
6bbd11
+			}
6bbd11
+			break;
6bbd11
+
6bbd11
+		case '/':
6bbd11
+			len++;
6bbd11
+			if (dst)
6bbd11
+				*dst++ = ch;
6bbd11
+
6bbd11
+			if (!(flags & CONF_NORMALIZE_SLASHES))
6bbd11
+				break;
6bbd11
+
6bbd11
+			/* Double slash at start is allowed */
6bbd11
+			if (src == (o_src + 1) && *src == '/') {
6bbd11
+				len++;
6bbd11
+				if (dst)
6bbd11
+					*dst++ = *src;
6bbd11
+				src++;
6bbd11
+			}
6bbd11
+			while (*src == '/')
6bbd11
+				src++;
6bbd11
+			break;
6bbd11
+
6bbd11
+		case '"':
6bbd11
+			len++;
6bbd11
+			if (dst)
6bbd11
+				*dst++ = ch;
6bbd11
+
6bbd11
+			while (*src && *src != '"') {
6bbd11
+				len++;
6bbd11
+				if (dst)
6bbd11
+					*dst++ = *src;
6bbd11
+				src++;
6bbd11
+			}
6bbd11
+			if (*src) {
6bbd11
+				len++;
6bbd11
+				if (dst)
6bbd11
+					*dst++ = *src;
6bbd11
+				src++;
6bbd11
+			}
6bbd11
+			break;
6bbd11
+
6bbd11
+		default:
6bbd11
+			if (dst)
6bbd11
+				*(dst++) = ch;
6bbd11
+			len++;
6bbd11
+			break;
6bbd11
+		}
6bbd11
+	}
6bbd11
+	if (dst)
6bbd11
+		*dst = '\0';
6bbd11
+
6bbd11
+	return len;
6bbd11
+}
6bbd11
+
6bbd11
+int expand_selectors(struct autofs_point *ap,
6bbd11
+		     const char *mapstr, char **pmapstr,
6bbd11
+		     struct substvar *sv)
6bbd11
+{
6bbd11
+	char buf[MAX_ERR_BUF];
6bbd11
+	char *expand;
6bbd11
+	size_t len;
6bbd11
+
6bbd11
+	if (!mapstr)
6bbd11
+		return 0;
6bbd11
+
6bbd11
+	len = expandamdent(mapstr, NULL, sv);
6bbd11
+	if (len == 0) {
6bbd11
+		error(ap->logopt, "failed to expand map entry");
6bbd11
+		return 0;
6bbd11
+	}
6bbd11
+
6bbd11
+	expand = malloc(len + 1);
6bbd11
+	if (!expand) {
6bbd11
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
6bbd11
+		error(ap->logopt, "malloc: %s", estr);
6bbd11
+		return 0;
6bbd11
+	}
6bbd11
+	memset(expand, 0, len + 1);
6bbd11
+
6bbd11
+	expandamdent(mapstr, expand, sv);
6bbd11
+
6bbd11
+	*pmapstr = expand;
6bbd11
+
6bbd11
+	return len;
6bbd11
+}
6bbd11
+
6bbd11
 void free_map_type_info(struct map_type_info *info)
6bbd11
 {
6bbd11
 	if (info->type)