1 1.1 christos /* $NetBSD: id2entry.c,v 1.3 2025/09/05 21:16:31 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* OpenLDAP WiredTiger backend */ 4 1.1 christos /* $OpenLDAP$ */ 5 1.1 christos /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 1.1 christos * 7 1.3 christos * Copyright 2002-2024 The OpenLDAP Foundation. 8 1.1 christos * All rights reserved. 9 1.1 christos * 10 1.1 christos * Redistribution and use in source and binary forms, with or without 11 1.1 christos * modification, are permitted only as authorized by the OpenLDAP 12 1.1 christos * Public License. 13 1.1 christos * 14 1.1 christos * A copy of this license is available in the file LICENSE in the 15 1.1 christos * top-level directory of the distribution or, alternatively, at 16 1.1 christos * <http://www.OpenLDAP.org/license.html>. 17 1.1 christos */ 18 1.1 christos /* ACKNOWLEDGEMENTS: 19 1.1 christos * This work was developed by HAMANO Tsukasa <hamano (at) osstech.co.jp> 20 1.1 christos * based on back-bdb for inclusion in OpenLDAP Software. 21 1.1 christos * WiredTiger is a product of MongoDB Inc. 22 1.1 christos */ 23 1.1 christos 24 1.1 christos #include "back-wt.h" 25 1.1 christos #include "slap-config.h" 26 1.1 christos 27 1.1 christos static int wt_id2entry_put( 28 1.1 christos Operation *op, 29 1.3 christos wt_ctx *wc, 30 1.1 christos Entry *e, 31 1.3 christos WT_CURSOR *cursor) 32 1.1 christos { 33 1.1 christos struct berval bv; 34 1.1 christos WT_ITEM item; 35 1.1 christos int rc; 36 1.1 christos 37 1.1 christos rc = entry_encode( e, &bv ); 38 1.1 christos if(rc != LDAP_SUCCESS){ 39 1.1 christos return -1; 40 1.1 christos } 41 1.1 christos item.size = bv.bv_len; 42 1.1 christos item.data = bv.bv_val; 43 1.1 christos 44 1.1 christos cursor->set_key(cursor, e->e_id); 45 1.1 christos cursor->set_value(cursor, e->e_ndn, &item); 46 1.1 christos rc = cursor->insert(cursor); 47 1.1 christos if ( rc ) { 48 1.1 christos Debug( LDAP_DEBUG_ANY, 49 1.3 christos "wt_id2entry_put: insert failed: %s (%d)\n", 50 1.1 christos wiredtiger_strerror(rc), rc ); 51 1.1 christos goto done; 52 1.1 christos } 53 1.1 christos 54 1.1 christos done: 55 1.1 christos ch_free( bv.bv_val ); 56 1.3 christos 57 1.1 christos return rc; 58 1.1 christos } 59 1.1 christos 60 1.1 christos int wt_id2entry_add( 61 1.1 christos Operation *op, 62 1.3 christos wt_ctx *wc, 63 1.1 christos Entry *e ) 64 1.1 christos { 65 1.3 christos WT_SESSION *session = wc->session; 66 1.3 christos WT_CURSOR *cursor = wc->id2entry_add; 67 1.3 christos int rc; 68 1.3 christos 69 1.3 christos if(!cursor){ 70 1.3 christos rc = session->open_cursor(session, WT_TABLE_ID2ENTRY, NULL, 71 1.3 christos "overwrite=false", &cursor); 72 1.3 christos if ( rc ) { 73 1.3 christos Debug( LDAP_DEBUG_ANY, 74 1.3 christos "wt_id2entry_put: open_cursor failed: %s (%d)\n", 75 1.3 christos wiredtiger_strerror(rc), rc ); 76 1.3 christos return rc; 77 1.3 christos } 78 1.3 christos wc->id2entry_add = cursor; 79 1.3 christos } 80 1.3 christos 81 1.3 christos rc = wt_id2entry_put(op, wc, e, cursor); 82 1.3 christos 83 1.3 christos #ifdef WT_CURSOR_CACHE 84 1.3 christos if(cursor){ 85 1.3 christos cursor->reset(cursor); 86 1.3 christos } 87 1.3 christos #else 88 1.3 christos if(cursor){ 89 1.3 christos cursor->close(cursor); 90 1.3 christos wc->id2entry_add = NULL; 91 1.3 christos } 92 1.3 christos #endif 93 1.3 christos 94 1.3 christos return rc; 95 1.1 christos } 96 1.1 christos 97 1.1 christos int wt_id2entry_update( 98 1.1 christos Operation *op, 99 1.3 christos wt_ctx *wc, 100 1.1 christos Entry *e ) 101 1.1 christos { 102 1.3 christos WT_SESSION *session = wc->session; 103 1.3 christos WT_CURSOR *cursor = wc->id2entry_update; 104 1.3 christos int rc; 105 1.3 christos 106 1.3 christos if(!cursor){ 107 1.3 christos rc = session->open_cursor(session, WT_TABLE_ID2ENTRY, NULL, 108 1.3 christos "overwrite=true", &cursor); 109 1.3 christos if ( rc ) { 110 1.3 christos Debug( LDAP_DEBUG_ANY, 111 1.3 christos "wt_id2entry_put: open_cursor failed: %s (%d)\n", 112 1.3 christos wiredtiger_strerror(rc), rc ); 113 1.3 christos return rc; 114 1.3 christos } 115 1.3 christos wc->id2entry_update = cursor; 116 1.3 christos } 117 1.3 christos rc = wt_id2entry_put(op, wc, e, cursor); 118 1.3 christos 119 1.3 christos #ifdef WT_CURSOR_CACHE 120 1.3 christos if(cursor){ 121 1.3 christos cursor->reset(cursor); 122 1.3 christos } 123 1.3 christos #else 124 1.3 christos if(cursor){ 125 1.3 christos cursor->close(cursor); 126 1.3 christos wc->id2entry_update = NULL; 127 1.3 christos } 128 1.3 christos #endif 129 1.3 christos return rc; 130 1.1 christos } 131 1.1 christos 132 1.1 christos int wt_id2entry_delete( 133 1.1 christos Operation *op, 134 1.3 christos wt_ctx *wc, 135 1.1 christos Entry *e ) 136 1.1 christos { 137 1.1 christos int rc; 138 1.3 christos WT_SESSION *session = wc->session; 139 1.1 christos WT_CURSOR *cursor = NULL; 140 1.3 christos 141 1.1 christos rc = session->open_cursor(session, WT_TABLE_ID2ENTRY, NULL, 142 1.1 christos NULL, &cursor); 143 1.1 christos if ( rc ) { 144 1.1 christos Debug( LDAP_DEBUG_ANY, 145 1.3 christos "wt_id2entry_delete: open_cursor failed: %s (%d)\n", 146 1.1 christos wiredtiger_strerror(rc), rc ); 147 1.1 christos goto done; 148 1.1 christos } 149 1.1 christos cursor->set_key(cursor, e->e_id); 150 1.1 christos rc = cursor->remove(cursor); 151 1.1 christos if ( rc ) { 152 1.1 christos Debug( LDAP_DEBUG_ANY, 153 1.3 christos "wt_id2entry_delete: remove failed: %s (%d)\n", 154 1.1 christos wiredtiger_strerror(rc), rc ); 155 1.1 christos goto done; 156 1.1 christos } 157 1.1 christos 158 1.1 christos done: 159 1.1 christos if(cursor){ 160 1.1 christos cursor->close(cursor); 161 1.1 christos } 162 1.1 christos return rc; 163 1.1 christos } 164 1.1 christos 165 1.1 christos int wt_id2entry( BackendDB *be, 166 1.3 christos wt_ctx *wc, 167 1.1 christos ID id, 168 1.1 christos Entry **ep ){ 169 1.1 christos int rc; 170 1.3 christos WT_SESSION *session = wc->session; 171 1.3 christos WT_CURSOR *cursor = wc->id2entry; 172 1.1 christos WT_ITEM item; 173 1.1 christos EntryHeader eh; 174 1.1 christos int eoff; 175 1.1 christos Entry *e = NULL; 176 1.1 christos 177 1.3 christos if(!cursor){ 178 1.3 christos rc = session->open_cursor(session, WT_TABLE_ID2ENTRY"(entry)", NULL, 179 1.3 christos NULL, &cursor); 180 1.3 christos if ( rc ) { 181 1.3 christos Debug( LDAP_DEBUG_ANY, 182 1.3 christos "wt_id2entry: open_cursor failed: %s (%d)\n", 183 1.3 christos wiredtiger_strerror(rc), rc ); 184 1.3 christos goto done; 185 1.3 christos } 186 1.3 christos wc->id2entry = cursor; 187 1.1 christos } 188 1.1 christos 189 1.1 christos cursor->set_key(cursor, id); 190 1.1 christos rc = cursor->search(cursor); 191 1.1 christos if ( rc ) { 192 1.1 christos goto done; 193 1.1 christos } 194 1.1 christos 195 1.1 christos cursor->get_value(cursor, &item); 196 1.1 christos rc = wt_entry_header( &item, &eh ); 197 1.1 christos eoff = eh.data - (char *)item.data; 198 1.1 christos eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + item.size; 199 1.1 christos eh.bv.bv_val = ch_malloc( eh.bv.bv_len ); 200 1.1 christos memset(eh.bv.bv_val, 0xff, eh.bv.bv_len); 201 1.1 christos eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval ); 202 1.1 christos memcpy(eh.data, item.data, item.size); 203 1.1 christos eh.data += eoff; 204 1.1 christos rc = entry_decode( &eh, &e ); 205 1.1 christos if ( rc ) { 206 1.1 christos Debug( LDAP_DEBUG_ANY, 207 1.3 christos "wt_id2entry: entry decode error: %s (%d)\n", 208 1.3 christos wiredtiger_strerror(rc), rc ); 209 1.1 christos goto done; 210 1.1 christos } 211 1.1 christos e->e_id = id; 212 1.1 christos *ep = e; 213 1.1 christos 214 1.1 christos done: 215 1.3 christos 216 1.3 christos #ifdef WT_CURSOR_CACHE 217 1.3 christos if(cursor){ 218 1.3 christos cursor->reset(cursor); 219 1.3 christos } 220 1.3 christos #else 221 1.1 christos if(cursor){ 222 1.1 christos cursor->close(cursor); 223 1.3 christos wc->id2entry = NULL; 224 1.1 christos } 225 1.3 christos #endif 226 1.1 christos return rc; 227 1.1 christos } 228 1.1 christos 229 1.1 christos int wt_entry_return( 230 1.1 christos Entry *e 231 1.1 christos ) 232 1.1 christos { 233 1.1 christos if ( !e ) { 234 1.1 christos return 0; 235 1.1 christos } 236 1.1 christos 237 1.3 christos /* Our entries are allocated in two blocks; the data comes from 238 1.1 christos * the db itself and the Entry structure and associated pointers 239 1.1 christos * are allocated in entry_decode. The db data pointer is saved 240 1.1 christos * in e_bv. 241 1.1 christos */ 242 1.1 christos if ( e->e_bv.bv_val ) { 243 1.1 christos #if 0 244 1.1 christos /* See if the DNs were changed by modrdn */ 245 1.1 christos if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val > 246 1.1 christos e->e_bv.bv_val + e->e_bv.bv_len ) { 247 1.1 christos ch_free(e->e_name.bv_val); 248 1.1 christos ch_free(e->e_nname.bv_val); 249 1.1 christos } 250 1.1 christos #endif 251 1.1 christos e->e_name.bv_val = NULL; 252 1.1 christos e->e_nname.bv_val = NULL; 253 1.1 christos /* In tool mode the e_bv buffer is realloc'd, leave it alone */ 254 1.1 christos if( !(slapMode & SLAP_TOOL_MODE) ) { 255 1.1 christos free( e->e_bv.bv_val ); 256 1.1 christos } 257 1.1 christos BER_BVZERO( &e->e_bv ); 258 1.1 christos } 259 1.1 christos 260 1.1 christos entry_free( e ); 261 1.3 christos return 0; 262 1.1 christos } 263 1.1 christos 264 1.1 christos int wt_entry_release( 265 1.1 christos Operation *op, 266 1.1 christos Entry *e, 267 1.1 christos int rw ) 268 1.1 christos { 269 1.1 christos return wt_entry_return( e ); 270 1.1 christos } 271 1.1 christos 272 1.1 christos /* 273 1.1 christos * return LDAP_SUCCESS IFF we can retrieve the specified entry. 274 1.1 christos */ 275 1.1 christos int wt_entry_get( 276 1.1 christos Operation *op, 277 1.1 christos struct berval *ndn, 278 1.1 christos ObjectClass *oc, 279 1.1 christos AttributeDescription *at, 280 1.1 christos int rw, 281 1.1 christos Entry **ent ) 282 1.1 christos { 283 1.3 christos struct wt_info *wi = (struct wt_info *) op->o_bd->be_private; 284 1.3 christos wt_ctx *wc; 285 1.3 christos Entry *e = NULL; 286 1.3 christos int rc; 287 1.3 christos const char *at_name = at ? at->ad_cname.bv_val : "(null)"; 288 1.3 christos 289 1.3 christos Debug( LDAP_DEBUG_ARGS, 290 1.3 christos "wt_entry_get: ndn: \"%s\"\n", ndn->bv_val ); 291 1.3 christos Debug( LDAP_DEBUG_ARGS, 292 1.3 christos "wt_entry_get: oc: \"%s\", at: \"%s\"\n", 293 1.3 christos oc ? oc->soc_cname.bv_val : "(null)", at_name ); 294 1.3 christos 295 1.3 christos wc = wt_ctx_get(op, wi); 296 1.3 christos if( !wc ){ 297 1.3 christos Debug( LDAP_DEBUG_ANY, 298 1.3 christos "wt_entry_get: wt_ctx_get failed\n" ); 299 1.3 christos return LDAP_OTHER; 300 1.3 christos } 301 1.3 christos rc = wt_dn2entry(op->o_bd, wc, ndn, &e); 302 1.3 christos switch( rc ) { 303 1.3 christos case 0: 304 1.3 christos break; 305 1.3 christos case WT_NOTFOUND: 306 1.3 christos Debug( LDAP_DEBUG_ACL, 307 1.3 christos "wt_entry_get: cannot find entry: \"%s\"\n", 308 1.3 christos ndn->bv_val ); 309 1.3 christos return LDAP_NO_SUCH_OBJECT; 310 1.3 christos default: 311 1.3 christos Debug( LDAP_DEBUG_ANY, 312 1.3 christos "wt_entry_get: wt_dn2entry failed %s rc=%d\n", 313 1.3 christos wiredtiger_strerror(rc), rc ); 314 1.3 christos rc = LDAP_OTHER; 315 1.3 christos } 316 1.3 christos 317 1.3 christos Debug( LDAP_DEBUG_ACL, 318 1.3 christos "wt_entry_get: found entry: \"%s\"\n", ndn->bv_val ); 319 1.3 christos 320 1.3 christos if ( oc && !is_entry_objectclass( e, oc, 0 )) { 321 1.3 christos Debug( LDAP_DEBUG_ACL, 322 1.3 christos "wt_entry_get: failed to find objectClass %s\n", 323 1.3 christos oc->soc_cname.bv_val ); 324 1.3 christos rc = LDAP_NO_SUCH_ATTRIBUTE; 325 1.3 christos goto return_results; 326 1.3 christos } 327 1.3 christos 328 1.3 christos /* NOTE: attr_find() or attrs_find()? */ 329 1.3 christos if ( at && attr_find( e->e_attrs, at ) == NULL ) { 330 1.3 christos Debug( LDAP_DEBUG_ACL, 331 1.3 christos "wt_entry_get: failed to find attribute %s\n", 332 1.3 christos at->ad_cname.bv_val ); 333 1.3 christos rc = LDAP_NO_SUCH_ATTRIBUTE; 334 1.3 christos goto return_results; 335 1.3 christos } 336 1.3 christos 337 1.3 christos return_results: 338 1.3 christos if( rc != LDAP_SUCCESS ) { 339 1.3 christos wt_entry_return( e ); 340 1.3 christos }else{ 341 1.3 christos *ent = e; 342 1.3 christos } 343 1.3 christos 344 1.3 christos Debug( LDAP_DEBUG_TRACE, "wt_entry_get: rc=%d\n", rc ); 345 1.3 christos 346 1.3 christos return rc; 347 1.1 christos } 348 1.1 christos 349 1.1 christos /* 350 1.1 christos * Local variables: 351 1.1 christos * indent-tabs-mode: t 352 1.1 christos * tab-width: 4 353 1.1 christos * c-basic-offset: 4 354 1.1 christos * End: 355 1.1 christos */ 356