From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13466 invoked by alias); 9 Sep 2009 08:58:17 -0000 Received: (qmail 13438 invoked by alias); 9 Sep 2009 08:58:16 -0000 X-SWARE-Spam-Status: No, hits=0.5 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_43,J_CHICKENPOX_61,J_CHICKENPOX_62,J_CHICKENPOX_63,J_CHICKENPOX_64,J_CHICKENPOX_65,J_CHICKENPOX_72,J_CHICKENPOX_73,SPF_HELO_PASS X-Spam-Status: No, hits=0.5 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_43,J_CHICKENPOX_61,J_CHICKENPOX_62,J_CHICKENPOX_63,J_CHICKENPOX_64,J_CHICKENPOX_65,J_CHICKENPOX_72,J_CHICKENPOX_73,SPF_HELO_PASS X-Spam-Check-By: sourceware.org X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on bastion2.fedora.phx.redhat.com Subject: cluster: STABLE3 - config: Add rng2ldif utility for LDIF maintenance To: cluster-cvs-relay@redhat.com X-Project: Cluster Project X-Git-Module: cluster.git X-Git-Refname: refs/heads/STABLE3 X-Git-Reftype: branch X-Git-Oldrev: d3d6c6ff20bf149507d47301a87033fb2af89bfd X-Git-Newrev: 6ba6404b0725fc61bd7df34734caa6b204ce1f28 From: "Fabio M. Di Nitto" Message-Id: <20090909085749.4FD6A12035B@lists.fedorahosted.org> Date: Wed, 09 Sep 2009 08:58:00 -0000 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Mailing-List: contact cluster-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: cluster-cvs-owner@sourceware.org X-SW-Source: 2009-q3/txt/msg00326.txt.bz2 Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=6ba6404b0725fc61bd7df34734caa6b204ce1f28 Commit: 6ba6404b0725fc61bd7df34734caa6b204ce1f28 Parent: d3d6c6ff20bf149507d47301a87033fb2af89bfd Author: Lon Hohberger AuthorDate: Tue Sep 8 13:18:31 2009 -0400 Committer: Fabio M. Di Nitto CommitterDate: Wed Sep 9 10:57:09 2009 +0200 config: Add rng2ldif utility for LDIF maintenance * Converts cluster.rng into 99cluster.ldif + ldap-base.csv * NOT an installed target at this point; used only for config schema maintenance * NOT automatically built at this point * Sample ldif-update target included in Makefile Signed-off-by: Lon Hohberger --- config/tools/ldap/rng2ldif/Makefile | 46 +++++ config/tools/ldap/rng2ldif/debug.h | 10 + config/tools/ldap/rng2ldif/genclass.c | 102 ++++++++++ config/tools/ldap/rng2ldif/ldaptypes.c | 53 ++++++ config/tools/ldap/rng2ldif/ldaptypes.h | 8 + config/tools/ldap/rng2ldif/name.c | 58 ++++++ config/tools/ldap/rng2ldif/name.h | 6 + config/tools/ldap/rng2ldif/rng2ldif.c | 212 +++++++++++++++++++++ config/tools/ldap/rng2ldif/tree.c | 311 +++++++++++++++++++++++++++++++ config/tools/ldap/rng2ldif/tree.h | 38 ++++ config/tools/ldap/rng2ldif/value-list.c | 192 +++++++++++++++++++ config/tools/ldap/rng2ldif/value-list.h | 29 +++ config/tools/ldap/rng2ldif/zalloc.c | 23 +++ config/tools/ldap/rng2ldif/zalloc.h | 6 + 14 files changed, 1094 insertions(+), 0 deletions(-) diff --git a/config/tools/ldap/rng2ldif/Makefile b/config/tools/ldap/rng2ldif/Makefile new file mode 100644 index 0000000..5192780 --- /dev/null +++ b/config/tools/ldap/rng2ldif/Makefile @@ -0,0 +1,46 @@ +TARGET1= rng2ldif +TARGET2= genclass + +all: ${TARGET1} ${TARGET2} + +include ../../../../make/defines.mk +include $(OBJDIR)/make/cobj.mk +include $(OBJDIR)/make/clean.mk +include $(OBJDIR)/make/install.mk +include $(OBJDIR)/make/uninstall.mk + +CFLAGS += -D_GNU_SOURCE +CFLAGS += -I. -I${incdir} +CFLAGS += `xml2-config --cflags` + +LDFLAGS += `xml2-config --libs` +LDFLAGS += -L${libdir} + +OBJS1= rng2ldif.o \ + tree.o + +OBJS2= genclass.o + +SHAREDOBJS= zalloc.o \ + value-list.o \ + ldaptypes.o \ + name.o + +${TARGET1}: ${SHAREDOBJS} ${OBJS1} + $(CC) -o $@ $^ $(EXTRA_LDFLAGS) $(LDFLAGS) + +${TARGET2}: ${SHAREDOBJS} ${OBJS2} + $(CC) -o $@ $^ $(LDFLAGS) + +ldif-update: all ../../../plugins/ldap/ldap-base.csv + make -C ../../xml cluster.rng + ./rng2ldif ../../xml/cluster.rng \ + ../../../plugins/ldap/ldap-base.csv \ + ../../../plugins/ldap/99cluster.ldif + + +clean: generalclean + +-include $(OBJS1:.o=.d) +-include $(OBJS2:.o=.d) +-include $(SHAREDOBJS:.o=.d) diff --git a/config/tools/ldap/rng2ldif/debug.h b/config/tools/ldap/rng2ldif/debug.h new file mode 100644 index 0000000..907e096 --- /dev/null +++ b/config/tools/ldap/rng2ldif/debug.h @@ -0,0 +1,10 @@ +#ifndef _DEBUG_H +#define _DEBUG_H + +#ifdef DEBUG +#define dbg_printf printf +#else +#define dbg_printf(args...) +#endif + +#endif diff --git a/config/tools/ldap/rng2ldif/genclass.c b/config/tools/ldap/rng2ldif/genclass.c new file mode 100644 index 0000000..7607714 --- /dev/null +++ b/config/tools/ldap/rng2ldif/genclass.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include + +#include +#include +#include "value-list.h" +#include "tree.h" + + +static void +id_gen_object_struct(struct idinfo *oi, FILE *fp) +{ + struct idval *v; + + fprintf(fp, "struct objectclasses\n"); + fprintf(fp, "{\n"); + fprintf(fp, "\tchar *name;\n"); + fprintf(fp, "\tchar *class;\n"); + fprintf(fp, "} objectclasses[] = \n"); + fprintf(fp, "{\n"); + + for (v = oi->head; v->next; v = v->next) { + if (v->type != OBJ) + continue; + fprintf(fp, "\t{ \"%s\", \"%s\" }, \n", + v->rawname, v->name); + } + + fprintf(fp, "\t{ \"%s\", \"%s\" }\n};\n", + v->rawname, v->name); +} + + +static int +write_class_struct(char *csv, char *arg, struct idinfo *ids) +{ + char filename[4096]; + FILE *out = NULL; + int fd = -1; + + if (!strcmp(arg, "-")) { + out = stdout; + } else { + snprintf(filename, sizeof(filename), "%s.XXXXXX", arg); + fd = mkstemp(filename); + if (fd < 0) { + perror("mkstemp"); + return -1; + } + + out = fdopen(fd, "w"); + if (out == NULL) { + perror("fdopen"); + close(fd); + return -1; + } + } + + fprintf(out, "/* Begin autogenerated class struct from %s */\n", csv); + id_gen_object_struct(ids, out); + fprintf(out, "/* End autogenerated class struct */\n"); + + fflush(out); + + if (fd >= 0) { + fsync(fd); + fclose(out); + close(fd); + rename(filename, arg); + } + + return 0; +} + + +int +main(int argc, char **argv) +{ + struct idinfo info; + + memset(&info, 0, sizeof(info)); + + if (argc < 3) { + printf("Translate csv -> C structure\n" + "file for future reuse of IDs\n"); + printf("Usage: %s file.csv output.c\n", + argv[0]); + return 1; + } + + if (id_readfile(&info, argv[1]) < 0) { + printf("Can't read %s\n", argv[1]); + return 1; + } + + write_class_struct(argv[1], argv[2], &info); + + return 0; +} diff --git a/config/tools/ldap/rng2ldif/ldaptypes.c b/config/tools/ldap/rng2ldif/ldaptypes.c new file mode 100644 index 0000000..beb0de9 --- /dev/null +++ b/config/tools/ldap/rng2ldif/ldaptypes.c @@ -0,0 +1,53 @@ +#include +#include +#include "ldaptypes.h" +#include "debug.h" + +struct type_entry { + const char *rng_name; + const char *ldap_equality; + const char *ldap_syntax; +}; + + +struct type_entry type_table[] = { +{ "boolean", "booleanMatch", "1.3.6.1.4.1.1466.115.121.1.7" }, +{ "integer", "integerMatch", "1.3.6.1.4.1.1466.115.121.1.27" }, +{ "positiveInteger", "integerMatch", "1.3.6.1.4.1.1466.115.121.1.27" }, +{ "nonNegativeInteger", "integerMatch", "1.3.6.1.4.1.1466.115.121.1.27" }, +{ "string", "caseExactIA5Match", "1.3.6.1.4.1.1466.115.121.1.26" }, +{ "ID", "caseExactIA5Match", "1.3.6.1.4.1.1466.115.121.1.26" }, +{ NULL, "caseExactIA5Match", "1.3.6.1.4.1.1466.115.121.1.26" } }; + + +void +find_ldap_type_info(const char *name, + char **equality, + char **syntax) +{ + int x; + + for (x = 0; type_table[x].rng_name != NULL; x++) + if (!strcasecmp(name, type_table[x].rng_name)) + break; + dbg_printf("%s @ index %d\n", name, x); + + *equality = (char *)type_table[x].ldap_equality; + *syntax = (char *)type_table[x].ldap_syntax; +} + + +#ifdef STANDALONE +#include +int +main(int argc, char **argv) +{ + char *eq, *syn; + + find_ldap_type_info(argv[1], &eq, &syn); + + printf("EQUALITY %s\nSYNTAX %s\n", eq, syn); + + return 0; +} +#endif diff --git a/config/tools/ldap/rng2ldif/ldaptypes.h b/config/tools/ldap/rng2ldif/ldaptypes.h new file mode 100644 index 0000000..1546cf3 --- /dev/null +++ b/config/tools/ldap/rng2ldif/ldaptypes.h @@ -0,0 +1,8 @@ +#ifndef _LDAPTYPES_H +#define _LDAPTYPES_H + +void find_ldap_type_info(const char *name, + char **equality, + char **syntax); + +#endif diff --git a/config/tools/ldap/rng2ldif/name.c b/config/tools/ldap/rng2ldif/name.c new file mode 100644 index 0000000..8cc5ef7 --- /dev/null +++ b/config/tools/ldap/rng2ldif/name.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include "name.h" +#include "zalloc.h" + +char * +normalize_name(const char *name) +{ + char *ret_val; + int size = 4, x; + + if (!strcasecmp(name, "name")) { + ret_val = strdup(name); + assert(ret_val!=NULL); + goto out; + } + + size = strlen(name)+5; + ret_val = zalloc(size); /* 1 byte for null, 4 for rhcs */ + if (!ret_val) + return NULL; + + snprintf(ret_val, size, "rhcs%s", name); + +out: + for (x = 0; x < 4; x++) + ret_val[x] |= 32; + if (ret_val[4] == '_') + ret_val[4] = '-'; + else + ret_val[4] &= ~32; + for (x = 5; x < size; x++) { + if (ret_val[x] == '_') { + ret_val[x] = '-'; + } + } + + return ret_val; +} + +#ifdef STANDALONE +int +main(int argc, char **argv) +{ + char *val; + if (argc < 2) + return -1; + + val = normalize_name(argv[1]); + if (!val) + fprintf(stderr, "oops\n"); + printf("%s\n", val); + free(val); + return 0; +} +#endif diff --git a/config/tools/ldap/rng2ldif/name.h b/config/tools/ldap/rng2ldif/name.h new file mode 100644 index 0000000..a332b45 --- /dev/null +++ b/config/tools/ldap/rng2ldif/name.h @@ -0,0 +1,6 @@ +#ifndef _NAME_H +#define _NAME_H + +char *normalize_name(const char *name); + +#endif diff --git a/config/tools/ldap/rng2ldif/rng2ldif.c b/config/tools/ldap/rng2ldif/rng2ldif.c new file mode 100644 index 0000000..39e2cbc --- /dev/null +++ b/config/tools/ldap/rng2ldif/rng2ldif.c @@ -0,0 +1,212 @@ +#include +#include +#include +#include +#include + +#include +#include +#include "value-list.h" +#include "tree.h" + + +struct faux_list { + struct faux_list *next; +}; + + +static void __attribute__((noinline)) +reverse(struct faux_list **list) +{ + struct faux_list *node = NULL; + struct faux_list *newlist = NULL; + + if (!list || (*list == NULL)) + return; + + while ((*list) != NULL) { + node = *list; + *list = node->next; + node->next = newlist; + newlist = node; + } + *list = node; +} + + +static int +print_attr_node(FILE *fp, struct ldap_attr_node *node) +{ + if (!node) + return -1; + if (!fp) + fp = stdout; + + if (!strcasecmp(node->name, "name")) { + /* Don't print 'name' out as an attr. */ + return 0; + } + + fprintf(fp, "attributeTypes: (\n"); + fprintf(fp, " 1.3.6.1.4.1.2312.8.1.1.%d NAME '%s'\n", + node->idval->value, node->name); + fprintf(fp, " EQUALITY %s\n", node->ldap_equality); + fprintf(fp, " SYNTAX %s\n", node->ldap_syntax); + fprintf(fp, " SINGLE-VALUE\n )\n"); + return 0; +} + + +static int +print_obj_node(FILE *fp, struct ldap_object_node *node) +{ + struct ldap_attr_meta_node *n; + const char *cmt = ""; + + if (!node) + return -1; + if (!fp) + fp = stdout; + + if (!node->required_attrs && !node->optional_attrs) { + cmt = "#"; + fprintf(fp, "### Placeholder for %s\n", node->name); + fprintf(fp, + "### This object class currently has no attributes\n"); + } + + fprintf(fp, "%sobjectClasses: (\n", cmt); + fprintf(fp, "%s 1.3.6.1.4.1.2312.8.1.2.%d NAME '%s' SUP top STRUCTURAL\n", cmt, node->idval->value, node->name); + + if (node->required_attrs) { + fprintf(fp, "%s MUST ( ", cmt); + for (n = node->required_attrs; n->next != NULL; n = n->next) + fprintf(fp, "%s $ ", n->node->name); + fprintf(fp, "%s )\n", n->node->name); + } + if (node->optional_attrs) { + fprintf(fp, "%s MAY ( ", cmt); + for (n = node->optional_attrs; n->next != NULL; n = n->next) + fprintf(fp, "%s $ ", n->node->name); + fprintf(fp, "%s )\n", n->node->name); + } + fprintf(fp, "%s )\n", cmt); + return 0; +} + + +static xmlDocPtr +open_relaxng(const char *filename) +{ + xmlDocPtr p; + xmlNodePtr n; + + p = xmlParseFile(filename); + if (!p) { + printf("Failed to parse %s\n", filename); + } + + n = xmlDocGetRootElement(p); + if (xmlStrcmp(n->name, (xmlChar *)"grammar")) { + printf("%s is not a relaxng grammar\n", filename); + xmlFreeDoc(p); + return NULL; + } + + return p; +} + + +static int +write_ldap_schema(const char *rng, const char *arg, + struct ldap_attr_node *attrs, + struct ldap_object_node *objs) +{ + struct ldap_attr_node *attr = NULL; + struct ldap_object_node *obj = NULL; + char filename[4096]; + FILE *out_ldap = NULL; + int fd = -1; + + if (!strcmp(arg, "-")) { + out_ldap = stdout; + } else { + snprintf(filename, sizeof(filename), "%s.XXXXXX", arg); + fd = mkstemp(filename); + if (fd < 0) { + perror("mkstemp"); + return -1; + } + + out_ldap = fdopen(fd, "w"); + if (out_ldap == NULL) { + perror("fdopen"); + close(fd); + return -1; + } + } + + fprintf(out_ldap, "# Auto-generated from %s\n", rng); + fprintf(out_ldap, "dn: cn=schema\n"); + + for (attr = attrs; attr; attr = attr->next) + print_attr_node(out_ldap, attr); + for (obj = objs; obj; obj= obj->next) + print_obj_node(out_ldap, obj); + + fflush(out_ldap); + + if (fd >= 0) { + fsync(fd); + fclose(out_ldap); + close(fd); + rename(filename, arg); + } + + return 0; +} + + +int +main(int argc, char **argv) +{ + struct ldap_attr_node *attrs = NULL; + struct ldap_object_node *objs = NULL; + struct idinfo info; + xmlDocPtr doc; + + memset(&info, 0, sizeof(info)); + + if (argc < 4) { + printf("Translate cluster RelaxNG -> LDIF schema and update\n" + "global .csv file for future reuse of IDs\n"); + printf("Usage: %s cluster.rng ldap-base.csv cluster.ldif\n", + argv[0]); + return 1; + } + + doc = open_relaxng(argv[1]); + if (doc == NULL) { + printf("Cannot continue\n"); + return 1; + } + + if (id_readfile(&info, argv[2]) < 0) { + printf("Can't read %s\n", argv[2]); + return 1; + } + + if (find_objects(xmlDocGetRootElement(doc), + &objs, &attrs, &info) < 0) + return 1; + + reverse((struct faux_list **)&attrs); + reverse((struct faux_list **)&objs); + + if (write_ldap_schema(argv[1], argv[3], attrs, objs) < 0) + return -1; + + id_writefile(&info, argv[2]); + + return 0; +} diff --git a/config/tools/ldap/rng2ldif/tree.c b/config/tools/ldap/rng2ldif/tree.c new file mode 100644 index 0000000..a6e0b46 --- /dev/null +++ b/config/tools/ldap/rng2ldif/tree.c @@ -0,0 +1,311 @@ +#include +#include +#include +#include +#include + +#include "zalloc.h" +#include "value-list.h" +#include "tree.h" +#include "name.h" +#include "ldaptypes.h" +#include "debug.h" + + +static struct ldap_attr_node * +find_attr(struct ldap_attr_node *attrs, const char *name) +{ + struct ldap_attr_node *n; + + for (n = attrs; n; n = n->next) { + if (!strcmp(n->name, name)) + return n; + } + return NULL; +} + + +static struct ldap_attr_meta_node * +find_meta_attr(struct ldap_attr_meta_node *metas, struct ldap_attr_node *attr) +{ + struct ldap_attr_meta_node *n; + + for (n = metas; n; n = n->next) { + if (n->node == attr) + return n; + } + return NULL; +} + + +static int +find_data_match_fn(xmlNodePtr curr_node, char **match_fn, char **ldap_syntax) +{ + xmlNodePtr n = NULL; + char *type = NULL; + int need_free = 1; + + for (n = curr_node; n; n = n->next) { + if (!n->name || + strcasecmp((char *)n->name, "data")) + continue; + break; + } + + if (n) + type = (char *)xmlGetProp(n, (xmlChar *)"type"); + + dbg_printf("type %s\n", type); + + if (!type) { + type = (char *)"string"; + need_free = 0; + } + + find_ldap_type_info(type, match_fn, ldap_syntax); + + if (need_free) + xmlFree(type); + + return 1; +} + + +static struct ldap_attr_node * +get_attr(xmlNodePtr curr_node, struct ldap_attr_node **attrs, + struct idinfo *ids) +{ + struct ldap_attr_node *n; + struct idval *v; + char *name, *normalized; + + name = (char *)xmlGetProp(curr_node, (xmlChar *)"name"); + normalized = normalize_name((const char *)name); + + n = find_attr(*attrs, normalized); + if (n) { + free(normalized); + return n; + } + + n = zalloc(sizeof(*n)); + + v = id_find(ids, normalized, ATTR, 0); + if (!v) { + v = zalloc(sizeof(*v)); + v->name = normalized; + v->type = ATTR; + v->rawname = (char *)name; + id_insert(ids, v); + } else { + free(normalized); + } + + n->idval = v; + n->name = n->idval->name; + + dbg_printf("Lookin for data type for %s\n", n->name); + find_data_match_fn(curr_node->xmlChildrenNode, &n->ldap_equality, + &n->ldap_syntax); + + n->next = *attrs; + *attrs = n; + + return n; +} + + +static struct ldap_object_node * +find_obj(struct ldap_object_node *objs, const char *name) +{ + struct ldap_object_node *n; + + for (n = objs; n; n = n->next) { + if (!strcmp(n->name, name)) + return n; + } + return NULL; +} + + + +static int +find_optional_attributes(xmlNodePtr curr_node, int in_block, + struct ldap_object_node *curr_obj, + struct ldap_attr_node **attrs, + struct idinfo *ids) +{ + xmlNodePtr node; + struct ldap_attr_node *attr; + struct ldap_attr_meta_node *n; + + if (!curr_node || (curr_node->type == XML_ELEMENT_NODE && + (curr_node->name && !strcasecmp((char *)curr_node->name, "element")))) { + return 0; + } + + dbg_printf("lookin for optionals\n"); + + for (node = curr_node; node; node = node->next) { + if (node->type != XML_ELEMENT_NODE) + continue; + if (!strcasecmp((char *)node->name, "choice")) { + find_optional_attributes(node->xmlChildrenNode, 1, + curr_obj, + attrs, ids); + continue; + } + if (!strcasecmp((char *)node->name, "group")) { + find_optional_attributes(node->xmlChildrenNode, 1, + curr_obj, + attrs, ids); + continue; + } + if (!strcasecmp((char *)node->name, "optional")) { + find_optional_attributes(node->xmlChildrenNode, 1, + curr_obj, + attrs, ids); + continue; + } + + if (!node->name || strcmp((char *)node->name, + "attribute")) { + continue; + } + + if (!in_block) + continue; + + attr = get_attr(node, attrs, ids); + n = zalloc(sizeof(*n)); + + dbg_printf("opt attr '%s'\n", attr->idval->name); + + if (find_meta_attr(curr_obj->required_attrs, + attr)) { + dbg_printf("skipping dup attr\n"); + continue; + } + if (find_meta_attr(curr_obj->optional_attrs, + attr)) { + dbg_printf("skipping dup attr on optional list\n"); + continue; + } + + n->node = attr; + n->next = curr_obj->optional_attrs; + curr_obj->optional_attrs = n; + } + return 0; +} + + +static int +find_required_attributes(xmlNodePtr curr_node, + struct ldap_object_node *curr_obj, + struct ldap_attr_node **attrs, + struct idinfo *ids) +{ + xmlNodePtr node; + struct ldap_attr_node *attr; + struct ldap_attr_meta_node *n; + + dbg_printf("lookin for required\n"); + + for (node = curr_node; node; node = node->next) { + if (node->type != XML_ELEMENT_NODE) + continue; + if (xmlStrcmp(node->name, (xmlChar *)"attribute")) + continue; + + attr = get_attr(node, attrs, ids); + n = zalloc(sizeof(*n)); + + dbg_printf("req attr '%s'\n", attr->idval->name); + + if (find_meta_attr(curr_obj->required_attrs, + attr)) { + dbg_printf("skipping dup attr\n"); + continue; + } + if (find_meta_attr(curr_obj->optional_attrs, + attr)) { + dbg_printf("skipping dup attr on optional list\n"); + continue; + } + + n->node = attr; + n->next = curr_obj->required_attrs; + curr_obj->required_attrs = n; + } + return 0; +} + + +static void +parse_element_tag(xmlNodePtr curr_node, + struct ldap_object_node **objs, + struct ldap_attr_node **attrs, + struct idinfo *ids) +{ + struct ldap_object_node *obj; + char *n, *normalized; + struct idval *v; + + dbg_printf("Trying to parse element tag\n"); + n = (char *)xmlGetProp(curr_node, (xmlChar *)"name"); + normalized = normalize_name(n); + v = id_find(ids, normalized, OBJ, 0); + + if (!v) { + v = zalloc(sizeof(*v)); + v->name = normalized; + v->rawname = n; + v->type = OBJ; + id_insert(ids, v); + } + + obj = find_obj(*objs, v->name); + + if (!obj) { + obj = zalloc(sizeof(*obj)); + obj->name = v->name; + obj->idval = v; + obj->next = *objs; + *objs = obj; + dbg_printf("New object class %s \n",obj->name); + } + + find_optional_attributes(curr_node->xmlChildrenNode, 0, + obj, attrs, ids); + find_required_attributes(curr_node->xmlChildrenNode, + obj, attrs, ids); +} + + +int +find_objects(xmlNodePtr curr_node, + struct ldap_object_node **objs, + struct ldap_attr_node **attrs, + struct idinfo *ids) +{ + //xmlNodePtr node; + + if (!curr_node) + return 0; + + for (; curr_node; curr_node = curr_node->next) { + if (curr_node->type != XML_ELEMENT_NODE) + continue; + if (!strcasecmp((char *)curr_node->name, "element")) { + parse_element_tag(curr_node, objs, attrs, ids); + } else { + dbg_printf("Descend on %s\n", curr_node->name); + } + find_objects(curr_node->xmlChildrenNode, + objs, attrs, ids); + + } + + return 0; +} diff --git a/config/tools/ldap/rng2ldif/tree.h b/config/tools/ldap/rng2ldif/tree.h new file mode 100644 index 0000000..098f4b6 --- /dev/null +++ b/config/tools/ldap/rng2ldif/tree.h @@ -0,0 +1,38 @@ +#ifndef _TREE_H +#define _TREE_H + +struct ldap_attr_list { + struct ldap_attr_node *head, *tail; +}; + +struct ldap_attr_node { + struct ldap_attr_node *next; + char *name; /* self->idval->name; do not free() */ + char *desc; + char *ldap_equality; + char *ldap_syntax; + struct idval *idval; +}; + +struct ldap_attr_meta_node { + struct ldap_attr_meta_node *next; + struct ldap_attr_node *node; +}; + +struct ldap_object_node { + struct ldap_object_node *next; + char *name; /* self->idval->name; do not free() */ + char *desc; + struct idval *idval; + struct ldap_attr_meta_node *optional_attrs; + struct ldap_attr_meta_node *required_attrs; +}; + +int +find_objects(xmlNodePtr curr_node, + struct ldap_object_node **objs, + struct ldap_attr_node **attrs, + struct idinfo *ids); + + +#endif diff --git a/config/tools/ldap/rng2ldif/value-list.c b/config/tools/ldap/rng2ldif/value-list.c new file mode 100644 index 0000000..d8b0e84 --- /dev/null +++ b/config/tools/ldap/rng2ldif/value-list.c @@ -0,0 +1,192 @@ +/** License: GPLv2 */ +#include +#include +#include +#include +#include +#include "value-list.h" +#include "zalloc.h" + +void +id_insert(struct idinfo *i, struct idval *v) +{ + if (v->type == ATTR) { + if (v->value > i->max_attr) + i->max_attr = v->value; + if (!v->value) + v->value = ++i->max_attr; + } else /* if type == OBJ */ { + if (v->value > i->max_obj) + i->max_obj = v->value; + if (!v->value) + v->value = ++i->max_obj; + } + + if (!i->head) + i->head = v; + if (i->tail) + i->tail->next = v; + i->tail = v; +} + + +struct idval * +id_find(struct idinfo *oi, const char *val, int type, int id) +{ + struct idval *v; + + if (!val && !id) + return NULL; + + /* linear search */ + for (v = oi->head; v; v = v->next) { + if (v->type != type) + continue; + if (val && !strcmp(val, v->name)) + return v; + if (id && id == v->value) + return v; + } + + return NULL; +} + + +void +id_dump(struct idinfo *oi, FILE *fp) +{ + struct idval *v; + + fprintf(fp, "# Max attribute value: %d\n", oi->max_attr); + fprintf(fp, "# Max object class value: %d\n", oi->max_obj); + + for (v = oi->head; v; v = v->next) { + fprintf(fp, "%s,%s,%s,%d\n", v->type==OBJ?"obj":"attr", + v->name, v->rawname, v->value); + } +} + + + +int +id_writefile(struct idinfo *oi, char *filename) +{ + char tmpfn[4096]; + FILE *fp; + int fd; + + snprintf(tmpfn, sizeof(tmpfn), "%s.XXXXXX", filename); + fd = mkstemp(tmpfn); + if (fd < 0) + return -1; + + fp = fdopen(fd, "w"); + if (!fp) { + close(fd); + unlink(tmpfn); + return -1; + } + + id_dump(oi, fp); + fflush(fp); + fsync(fd); + fclose(fp); + close(fd); + + /* done */ + rename(tmpfn, filename); + + return 0; +} + + +int +id_readfile(struct idinfo *oi, char *filename) +{ + char *c, *valp; + struct idval *v; + struct idval *tmp; + FILE *fp; + char buf[4096]; + int len, lineno = 0, entries = 0; + + fp = fopen(filename, "r"); + if (!filename) { + perror("fopen"); + return 1; + } + + while (fgets(buf, sizeof(buf), fp)) { + ++lineno; + if (!strlen(buf)) + continue; + if (buf[0] == '#') + continue; + len = strlen(buf); + while (buf[len-1] < ' ') { + buf[len-1] = 0; + --len; + } + v = zalloc(sizeof(*v)); + + /* Attribute / object */ + c = strchr(buf, ','); + if (!c || strlen(c) == 1) { + fprintf(stderr, + "%s: Malformed input on line %d: '%s'\n", + filename, lineno, buf); + exit(-2); + } + + *c = 0; + c++; + if (!strncasecmp(buf, "attr",4)) { + v->type = ATTR; + } else if (!strncasecmp(buf, "obj", 3)) { + v->type = OBJ; + } else { + fprintf(stderr, "%s: Unknown type on line %d: '%s'\n", + filename, lineno, buf); + exit(-2); + } + + valp = strchr(c, ','); + if (valp) { + *valp = 0; + valp++; + } + v->name = strdup(c); + assert(v->name); + + c = valp; + + valp = strchr(c, ','); + v->value = 0; + if (valp) { + *valp = 0; + valp++; + if (strlen(valp)) + v->value = atoi(valp); + } + + v->rawname = strdup(c); + assert(v->rawname); + + if (!id_find(oi, v->name, v->type, 0)) { + tmp = id_find(oi, NULL, v->type, v->value); + if (tmp) { + fprintf(stderr, "%s: Duplicate id value: " + "%d & %d, type %d\n", filename, + tmp->value, v->value, v->type); + exit(-1); + } + id_insert(oi, v); + } + + ++entries; + } + + fclose(fp); + + return 0; +} diff --git a/config/tools/ldap/rng2ldif/value-list.h b/config/tools/ldap/rng2ldif/value-list.h new file mode 100644 index 0000000..4e83e08 --- /dev/null +++ b/config/tools/ldap/rng2ldif/value-list.h @@ -0,0 +1,29 @@ +/** License: GPLv2 */ +#ifndef _VALUE_LIST_H +#define _VALUE_LIST_H + +struct idval { + struct idval *next; + char *name; + char *rawname; + int type; + int value; +}; + +struct idinfo { + struct idval *head; + struct idval *tail; + int max_obj; + int max_attr; +}; + +void id_insert(struct idinfo *i, struct idval *v); +struct idval * id_find(struct idinfo *oi, const char *val, int type, int id); +void id_dump(struct idinfo *oi, FILE *fp); +int id_readfile(struct idinfo *oi, char *filename); +int id_writefile(struct idinfo *oi, char *filename); + +#define OBJ 1 +#define ATTR 0 + +#endif diff --git a/config/tools/ldap/rng2ldif/zalloc.c b/config/tools/ldap/rng2ldif/zalloc.c new file mode 100644 index 0000000..f05306d --- /dev/null +++ b/config/tools/ldap/rng2ldif/zalloc.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include "zalloc.h" + +void * +zalloc(size_t size) +{ + void *ret; + size_t oddball; + + oddball = ( size % sizeof(void *) ); + if (oddball) { + size -= oddball; + size += sizeof(void *); + } + + ret = malloc(size); + if (!ret) + assert(0); + memset(ret, 0, size); + return ret; +} diff --git a/config/tools/ldap/rng2ldif/zalloc.h b/config/tools/ldap/rng2ldif/zalloc.h new file mode 100644 index 0000000..0992ec2 --- /dev/null +++ b/config/tools/ldap/rng2ldif/zalloc.h @@ -0,0 +1,6 @@ +#ifndef _ZALLOC_H +#define _ZALLOC_H + +void *zalloc(size_t size); + +#endif