|
146 |
MDB_val key, data; |
146 |
MDB_val key, data; |
147 |
subDN *subdn; |
147 |
subDN *subdn; |
148 |
DNID id = dnid; |
148 |
DNID id = dnid; |
|
|
149 |
LDAPDN ldapdn = NULL; |
150 |
char *dn_str; |
151 |
char *p; |
152 |
int i = 0; |
149 |
|
153 |
|
150 |
key.mv_size = sizeof(DNID); |
154 |
do { |
151 |
key.mv_data = &id; |
155 |
key.mv_size = sizeof(DNID); |
|
|
156 |
key.mv_data = &id; |
152 |
|
157 |
|
153 |
data.mv_size = sizeof(subDN); |
158 |
data.mv_size = sizeof(subDN); |
154 |
data.mv_data = &(subDN){0, SUBDN_TYPE_NODE, ""}; |
159 |
data.mv_data = &(subDN){0, SUBDN_TYPE_NODE, ""}; |
155 |
|
160 |
|
156 |
rv = mdb_cursor_get(cur, &key, &data, MDB_GET_BOTH); |
161 |
rv = mdb_cursor_get(cur, &key, &data, MDB_GET_BOTH); |
157 |
data.mv_data = NULL; |
162 |
data.mv_data = NULL; |
158 |
data.mv_size = 0; |
163 |
data.mv_size = 0; |
159 |
|
164 |
|
160 |
if (rv != MDB_SUCCESS) { |
165 |
if (rv != MDB_SUCCESS) { |
161 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: mdb_cursor_get (MDB_GET_BOTH): %s (%d)", __func__, mdb_strerror(rv), rv); |
166 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: mdb_cursor_get (MDB_GET_BOTH): %s (%d)", __func__, mdb_strerror(rv), rv); |
162 |
return rv; |
167 |
return rv; |
163 |
}; |
168 |
}; |
164 |
|
169 |
|
165 |
// Workaround for (ITS#8393) LMDB - MDB_GET_BOTH broken on non-dup value |
170 |
// Workaround for (ITS#8393) LMDB - MDB_GET_BOTH broken on non-dup value |
166 |
rv = mdb_cursor_get(cur, &key, &data, MDB_GET_CURRENT); |
171 |
rv = mdb_cursor_get(cur, &key, &data, MDB_GET_CURRENT); |
167 |
if (rv != MDB_SUCCESS) { |
172 |
if (rv != MDB_SUCCESS) { |
168 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: mdb_cursor_get: %s (%d)", __func__, mdb_strerror(rv), rv); |
173 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: mdb_cursor_get: %s (%d)", __func__, mdb_strerror(rv), rv); |
169 |
return rv; |
174 |
return rv; |
170 |
}; |
175 |
}; |
171 |
|
176 |
|
172 |
/* |
177 |
/* |
173 |
// or simply use this instead of MDB_GET_BOTH + MDB_GET_CURRENT: |
178 |
// or simply use this instead of MDB_GET_BOTH + MDB_GET_CURRENT: |
174 |
MDB_txn *txn; |
179 |
MDB_txn *txn; |
175 |
MDB_dbi dbi; |
180 |
MDB_dbi dbi; |
176 |
txn = mdb_cursor_txn(cur); |
181 |
txn = mdb_cursor_txn(cur); |
177 |
dbi = mdb_cursor_dbi(cur); |
182 |
dbi = mdb_cursor_dbi(cur); |
178 |
rv = mdb_get(txn, dbi, &key, &data); |
183 |
rv = mdb_get(txn, dbi, &key, &data); |
179 |
if (rv != MDB_SUCCESS) { |
184 |
if (rv != MDB_SUCCESS) { |
180 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
185 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
181 |
"%s: mdb_get: %s (%d)", |
186 |
"%s: mdb_get: %s (%d)", |
182 |
__func__, mdb_strerror(rv), rv); |
187 |
__func__, mdb_strerror(rv), rv); |
183 |
return rv; |
188 |
return rv; |
184 |
}; |
189 |
}; |
185 |
*/ |
190 |
*/ |
186 |
|
191 |
|
187 |
subdn = (subDN *)data.mv_data; |
192 |
if (!ldapdn) { |
|
|
193 |
i = 0; |
194 |
ldapdn = calloc(2, sizeof(LDAPDN)); |
195 |
} else { |
196 |
i++; |
197 |
ldapdn = realloc(ldapdn, (i+2)*sizeof(LDAPDN)); |
198 |
} |
199 |
if (ldapdn == NULL) { |
200 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: %s failed", __func__, i?"realloc":"calloc"); |
201 |
abort(); |
202 |
} |
188 |
|
203 |
|
189 |
*dn = strdup(subdn->data); |
204 |
ldapdn[i+1] = NULL; |
|
|
205 |
|
206 |
subdn = (subDN *)data.mv_data; |
207 |
rv = ldap_str2rdn(subdn->data, &ldapdn[i], &p, LDAP_DN_FORMAT_LDAP); |
208 |
if (rv != LDAP_SUCCESS) { |
209 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: ldap_str2rdn failed: %s (%d)", __func__, ldap_err2string(rv), rv); |
210 |
return rv; |
211 |
} |
212 |
|
213 |
if (ldapdn[i] == NULL) { |
214 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: ldap_str2rdn NULL: %s (%d): %s", __func__, ldap_err2string(rv), rv, subdn->data); |
215 |
return 1; |
216 |
} |
217 |
id = subdn->id; |
218 |
} while (id != 0); |
219 |
|
220 |
rv = ldap_dn2str(ldapdn, &dn_str, LDAP_DN_FORMAT_LDAPV3); |
221 |
ldap_dnfree(ldapdn); |
222 |
if (rv != LDAP_SUCCESS) { |
223 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: ldap_dn2str failed: %s (%d)", __func__, ldap_err2string(rv), rv); |
224 |
return rv; |
225 |
} |
226 |
|
227 |
*dn = strdup(dn_str); |
228 |
ldap_memfree(dn_str); |
190 |
if (*dn == NULL) { |
229 |
if (*dn == NULL) { |
191 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: strdup failed", __func__); |
230 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: strdup failed", __func__); |
192 |
abort(); |
231 |
abort(); |
|
218 |
DNID id; |
257 |
DNID id; |
219 |
char *rdn_str; |
258 |
char *rdn_str; |
220 |
char *dn_str; |
259 |
char *dn_str; |
221 |
size_t dn_len; |
|
|
222 |
size_t rdn_len; |
260 |
size_t rdn_len; |
223 |
subDN *subdn; |
261 |
subDN *subdn; |
224 |
|
262 |
|
|
241 |
|
279 |
|
242 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_INFO, "%s: child=%lu, parent=%lu: \"%s\"", __func__, child, parent, rdn_str); |
280 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_INFO, "%s: child=%lu, parent=%lu: \"%s\"", __func__, child, parent, rdn_str); |
243 |
|
281 |
|
244 |
dn_len = strlen(dn_str); |
282 |
rdn_len = strlen(rdn_str); |
245 |
subdn = calloc(1, sizeof(subDN) + dn_len); |
283 |
subdn = calloc(1, sizeof(subDN) + rdn_len); |
246 |
if (subdn == NULL) { |
284 |
if (subdn == NULL) { |
247 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: calloc failed", __func__); |
285 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "%s: calloc failed", __func__); |
248 |
ldap_memfree(dn_str); |
286 |
ldap_memfree(dn_str); |
|
249 |
ldap_memfree(rdn_str); |
287 |
ldap_memfree(rdn_str); |
250 |
abort(); |
288 |
abort(); |
251 |
} |
289 |
} |
252 |
rdn_len = strlen(rdn_str); |
|
|
253 |
assert(dn_len >= rdn_len); |
254 |
data.mv_size = sizeof(subDN) + rdn_len; |
290 |
data.mv_size = sizeof(subDN) + rdn_len; |
255 |
subdn->type = SUBDN_TYPE_LINK; |
291 |
subdn->type = SUBDN_TYPE_LINK; |
256 |
subdn->id = child; |
292 |
subdn->id = child; |
257 |
strcpy(subdn->data, rdn_str); |
293 |
strcpy(subdn->data, rdn_str); |
258 |
ldap_memfree(rdn_str); |
|
|
259 |
data.mv_data = subdn; |
294 |
data.mv_data = subdn; |
260 |
|
295 |
|
261 |
// Store subdn link |
296 |
// Store subdn link |
|
265 |
if (rv == MDB_SUCCESS) { |
300 |
if (rv == MDB_SUCCESS) { |
266 |
id = child; |
301 |
id = child; |
267 |
|
302 |
|
268 |
data.mv_size = sizeof(subDN) + dn_len; |
303 |
data.mv_size = sizeof(subDN) + rdn_len; |
269 |
subdn->type = SUBDN_TYPE_NODE; |
304 |
subdn->type = SUBDN_TYPE_NODE; |
270 |
subdn->id = parent; // backlink |
305 |
subdn->id = parent; // backlink |
271 |
strcpy(subdn->data, dn_str); |
306 |
strcpy(subdn->data, rdn_str); |
272 |
|
307 |
|
273 |
rv = mdb_cursor_put(write_cursor_p, &key, &data, MDB_NODUPDATA); |
308 |
rv = mdb_cursor_put(write_cursor_p, &key, &data, MDB_NODUPDATA); |
274 |
if (rv != MDB_SUCCESS) { |
309 |
if (rv != MDB_SUCCESS) { |
|
280 |
abort(); |
315 |
abort(); |
281 |
} |
316 |
} |
282 |
|
317 |
|
|
|
318 |
ldap_memfree(rdn_str); |
283 |
ldap_memfree(dn_str); |
319 |
ldap_memfree(dn_str); |
284 |
free(subdn); |
320 |
free(subdn); |
285 |
|
321 |
|