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;