public inbox for cluster-cvs@sourceware.org
help / color / mirror / Atom feed
* cluster: STABLE3 - config: Add rng2ldif utility for LDIF maintenance
@ 2009-09-09 8:58 Fabio M. Di Nitto
0 siblings, 0 replies; only message in thread
From: Fabio M. Di Nitto @ 2009-09-09 8:58 UTC (permalink / raw)
To: cluster-cvs-relay
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=6ba6404b0725fc61bd7df34734caa6b204ce1f28
Commit: 6ba6404b0725fc61bd7df34734caa6b204ce1f28
Parent: d3d6c6ff20bf149507d47301a87033fb2af89bfd
Author: Lon Hohberger <lhh@redhat.com>
AuthorDate: Tue Sep 8 13:18:31 2009 -0400
Committer: Fabio M. Di Nitto <fdinitto@redhat.com>
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 <lhh@redhat.com>
---
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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#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 <stdio.h>
+#include <string.h>
+#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 <stdio.h>
+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 <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#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 <malloc.h>
+#include <string.h>
+#include <assert.h>
+#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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2009-09-09 8:58 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-09 8:58 cluster: STABLE3 - config: Add rng2ldif utility for LDIF maintenance Fabio M. Di Nitto
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).