Blob Blame History Raw
autofs-5.0.999999999 - amd lookup add selector handling functions

From: Ian Kent <raven@themaw.net>


---
 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;