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;