--- src/README.md (Revision 77375) +++ src/README.md (Arbeitskopie) @@ -208,7 +208,7 @@ It links the *type=NODE* subDN with ID=*key* to the *type=NODE* subDN with ID=*id*. For any *non-root-node* a value with *type=NODE* will reference the parent node *id*. - *data* contains the full DN. + *data* contains the RDN. For any *non-leaf-node* a value with *type=LINK* will reference the direct child node *id*. *data* contains the relative DN of the child. --- src/cache_dn.c (Revision 77393) +++ src/cache_dn.c (Arbeitskopie) @@ -146,47 +146,86 @@ MDB_val key, data; subDN *subdn; DNID id = dnid; + LDAPDN ldapdn = NULL; + char *dn_str; + char *p; + int i = 0; - key.mv_size = sizeof(DNID); - key.mv_data = &id; + do { + key.mv_size = sizeof(DNID); + key.mv_data = &id; - data.mv_size = sizeof(subDN); - data.mv_data = &(subDN){0, SUBDN_TYPE_NODE, ""}; + data.mv_size = sizeof(subDN); + data.mv_data = &(subDN){0, SUBDN_TYPE_NODE, ""}; - rv = mdb_cursor_get(cur, &key, &data, MDB_GET_BOTH); - data.mv_data = NULL; - data.mv_size = 0; + rv = mdb_cursor_get(cur, &key, &data, MDB_GET_BOTH); + data.mv_data = NULL; + data.mv_size = 0; - if (rv != MDB_SUCCESS) { - univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: mdb_cursor_get (MDB_GET_BOTH): %s (%d)", __func__, mdb_strerror(rv), rv); - return rv; - }; + if (rv != MDB_SUCCESS) { + univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: mdb_cursor_get (MDB_GET_BOTH): %s (%d)", __func__, mdb_strerror(rv), rv); + return rv; + }; - // Workaround for (ITS#8393) LMDB - MDB_GET_BOTH broken on non-dup value - rv = mdb_cursor_get(cur, &key, &data, MDB_GET_CURRENT); - if (rv != MDB_SUCCESS) { - univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: mdb_cursor_get: %s (%d)", __func__, mdb_strerror(rv), rv); - return rv; - }; + // Workaround for (ITS#8393) LMDB - MDB_GET_BOTH broken on non-dup value + rv = mdb_cursor_get(cur, &key, &data, MDB_GET_CURRENT); + if (rv != MDB_SUCCESS) { + univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: mdb_cursor_get: %s (%d)", __func__, mdb_strerror(rv), rv); + return rv; + }; - /* - // or simply use this instead of MDB_GET_BOTH + MDB_GET_CURRENT: - MDB_txn *txn; - MDB_dbi dbi; - txn = mdb_cursor_txn(cur); - dbi = mdb_cursor_dbi(cur); - rv = mdb_get(txn, dbi, &key, &data); - if (rv != MDB_SUCCESS) { - univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, - "%s: mdb_get: %s (%d)", - __func__, mdb_strerror(rv), rv); - return rv; - }; - */ + /* + // or simply use this instead of MDB_GET_BOTH + MDB_GET_CURRENT: + MDB_txn *txn; + MDB_dbi dbi; + txn = mdb_cursor_txn(cur); + dbi = mdb_cursor_dbi(cur); + rv = mdb_get(txn, dbi, &key, &data); + if (rv != MDB_SUCCESS) { + univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, + "%s: mdb_get: %s (%d)", + __func__, mdb_strerror(rv), rv); + return rv; + }; + */ - subdn = (subDN *)data.mv_data; + if (!ldapdn) { + i = 0; + ldapdn = calloc(2, sizeof(LDAPDN)); + } else { + i++; + ldapdn = realloc(ldapdn, (i+2)*sizeof(LDAPDN)); + } + if (ldapdn == NULL) { + univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: %s failed", __func__, i?"realloc":"calloc"); + abort(); + } - *dn = strdup(subdn->data); + ldapdn[i+1] = NULL; + + subdn = (subDN *)data.mv_data; + rv = ldap_str2rdn(subdn->data, &ldapdn[i], &p, LDAP_DN_FORMAT_LDAP); + if (rv != LDAP_SUCCESS) { + univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: ldap_str2rdn failed: %s (%d)", __func__, ldap_err2string(rv), rv); + return rv; + } + + if (ldapdn[i] == NULL) { + univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: ldap_str2rdn NULL: %s (%d): %s", __func__, ldap_err2string(rv), rv, subdn->data); + return 1; + } + id = subdn->id; + } while (id != 0); + + rv = ldap_dn2str(ldapdn, &dn_str, LDAP_DN_FORMAT_LDAPV3); + ldap_dnfree(ldapdn); + if (rv != LDAP_SUCCESS) { + univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: ldap_dn2str failed: %s (%d)", __func__, ldap_err2string(rv), rv); + return rv; + } + + *dn = strdup(dn_str); + ldap_memfree(dn_str); if (*dn == NULL) { univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: strdup failed", __func__); abort(); @@ -218,7 +257,6 @@ DNID id; char *rdn_str; char *dn_str; - size_t dn_len; size_t rdn_len; subDN *subdn; @@ -241,8 +279,8 @@ univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_INFO, "%s: child=%lu, parent=%lu: \"%s\"", __func__, child, parent, rdn_str); - dn_len = strlen(dn_str); - subdn = calloc(1, sizeof(subDN) + dn_len); + rdn_len = strlen(rdn_str); + subdn = calloc(1, sizeof(subDN) + rdn_len); if (subdn == NULL) { univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: calloc failed", __func__); ldap_memfree(dn_str); @@ -249,13 +287,10 @@ ldap_memfree(rdn_str); abort(); } - rdn_len = strlen(rdn_str); - assert(dn_len >= rdn_len); data.mv_size = sizeof(subDN) + rdn_len; subdn->type = SUBDN_TYPE_LINK; subdn->id = child; strcpy(subdn->data, rdn_str); - ldap_memfree(rdn_str); data.mv_data = subdn; // Store subdn link @@ -265,10 +300,10 @@ if (rv == MDB_SUCCESS) { id = child; - data.mv_size = sizeof(subDN) + dn_len; + data.mv_size = sizeof(subDN) + rdn_len; subdn->type = SUBDN_TYPE_NODE; subdn->id = parent; // backlink - strcpy(subdn->data, dn_str); + strcpy(subdn->data, rdn_str); rv = mdb_cursor_put(write_cursor_p, &key, &data, MDB_NODUPDATA); if (rv != MDB_SUCCESS) { @@ -280,6 +315,7 @@ abort(); } + ldap_memfree(rdn_str); ldap_memfree(dn_str); free(subdn);