📄 search.c
字号:
bsi.bsi_e = NULL; bsi.bsi_n_candidates = ( op->ors_limit == NULL /* isroot == TRUE */ ? -2 : ( op->ors_limit->lms_s_unchecked == -1 ? -2 : ( op->ors_limit->lms_s_unchecked ) ) ); switch ( bsi.bsi_scope ) { case LDAP_SCOPE_BASE: case BACKSQL_SCOPE_BASE_LIKE: /* * probably already found... */ bsi.bsi_id_list = &bsi.bsi_base_id; bsi.bsi_id_listtail = &bsi.bsi_base_id.eid_next; break; case LDAP_SCOPE_SUBTREE: /* * if baseObject is defined, and if it is the root * of the search, add it to the candidate list */ if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &bsi.bsi_base_id.eid_id ) ) { bsi.bsi_id_list = &bsi.bsi_base_id; bsi.bsi_id_listtail = &bsi.bsi_base_id.eid_next; } /* FALLTHRU */ default: /* * for each objectclass we try to construct query which gets IDs * of entries matching LDAP query filter and scope (or at least * candidates), and get the IDs */ avl_apply( bi->sql_oc_by_oc, backsql_oc_get_candidates, &bsi, BACKSQL_AVL_STOP, AVL_INORDER ); /* check for abandon */ if ( op->o_abandon ) { eid = bsi.bsi_id_list; rs->sr_err = SLAPD_ABANDON; goto send_results; } } if ( op->ors_limit != NULL /* isroot == FALSE */ && op->ors_limit->lms_s_unchecked != -1 && bsi.bsi_n_candidates == -1 ) { rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; send_ldap_result( op, rs ); goto done; } /* * now we load candidate entries (only those attributes * mentioned in attrs and filter), test it against full filter * and then send to client; don't free entry_id if baseObject... */ for ( eid = bsi.bsi_id_list; eid != NULL; eid = backsql_free_entryID( op, eid, eid == &bsi.bsi_base_id ? 0 : 1 ) ) { int rc; Attribute *a_hasSubordinate = NULL, *a_entryUUID = NULL, *a_entryCSN = NULL, **ap = NULL; Entry *e = NULL; /* check for abandon */ if ( op->o_abandon ) { rs->sr_err = SLAPD_ABANDON; goto send_results; } /* check time limit */ if ( op->ors_tlimit != SLAP_NO_LIMIT && slap_get_time() > stoptime ) { rs->sr_err = LDAP_TIMELIMIT_EXCEEDED; rs->sr_ctrls = NULL; rs->sr_ref = rs->sr_v2ref; goto send_results; }#ifdef BACKSQL_ARBITRARY_KEY Debug(LDAP_DEBUG_TRACE, "backsql_search(): loading data " "for entry id=%s, oc_id=%ld, keyval=%s\n", eid->eid_id.bv_val, eid->eid_oc_id, eid->eid_keyval.bv_val );#else /* ! BACKSQL_ARBITRARY_KEY */ Debug(LDAP_DEBUG_TRACE, "backsql_search(): loading data " "for entry id=%ld, oc_id=%ld, keyval=%ld\n", eid->eid_id, eid->eid_oc_id, eid->eid_keyval );#endif /* ! BACKSQL_ARBITRARY_KEY */ /* check scope */ switch ( op->ors_scope ) { case LDAP_SCOPE_BASE: case BACKSQL_SCOPE_BASE_LIKE: if ( !dn_match( &eid->eid_ndn, &op->o_req_ndn ) ) { goto next_entry2; } break; case LDAP_SCOPE_ONE: { struct berval rdn = eid->eid_ndn; rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," ); if ( !dnIsOneLevelRDN( &rdn ) ) { goto next_entry2; } /* fall thru */ } case LDAP_SCOPE_SUBORDINATE: /* discard the baseObject entry */ if ( dn_match( &eid->eid_ndn, &op->o_req_ndn ) ) { goto next_entry2; } /* FALLTHRU */ case LDAP_SCOPE_SUBTREE: /* FIXME: this should never fail... */ if ( !dnIsSuffix( &eid->eid_ndn, &op->o_req_ndn ) ) { goto next_entry2; } break; } if ( BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) { /* don't recollect baseObject... */ e = bi->sql_baseObject; } else if ( eid == &bsi.bsi_base_id ) { /* don't recollect searchBase object... */ e = &base_entry; } else { bsi.bsi_e = &user_entry; rc = backsql_id2entry( &bsi, eid ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_search(): " "error %d in backsql_id2entry() " "- skipping\n", rc, 0, 0 ); continue; } e = &user_entry; } if ( !manageDSAit && op->ors_scope != LDAP_SCOPE_BASE && op->ors_scope != BACKSQL_SCOPE_BASE_LIKE && is_entry_referral( e ) ) { BerVarray refs; refs = get_entry_referrals( op, e ); if ( !refs ) { backsql_srch_info bsi2 = { 0 }; Entry user_entry2 = { 0 }; /* retry with the full entry... */ bsi2.bsi_e = &user_entry2; rc = backsql_init_search( &bsi2, &e->e_nname, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, NULL, BACKSQL_ISF_GET_ENTRY ); if ( rc == LDAP_SUCCESS ) { if ( is_entry_referral( &user_entry2 ) ) { refs = get_entry_referrals( op, &user_entry2 ); } else { rs->sr_err = LDAP_OTHER; } backsql_entry_clean( op, &user_entry2 ); } if ( bsi2.bsi_attrs != NULL ) { op->o_tmpfree( bsi2.bsi_attrs, op->o_tmpmemctx ); } } if ( refs ) { rs->sr_ref = referral_rewrite( refs, &e->e_name, &op->o_req_dn, op->ors_scope ); ber_bvarray_free( refs ); } if ( rs->sr_ref ) { rs->sr_err = LDAP_REFERRAL; } else { rs->sr_text = "bad referral object"; } rs->sr_entry = e; rs->sr_matched = user_entry.e_name.bv_val; send_search_reference( op, rs ); ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; rs->sr_matched = NULL; rs->sr_entry = NULL; goto next_entry; } /* * We use this flag since we need to parse the filter * anyway; we should have used the frontend API function * filter_has_subordinates() */ if ( bsi.bsi_flags & BSQL_SF_FILTER_HASSUBORDINATE ) { rc = backsql_has_children( op, dbh, &e->e_nname ); switch ( rc ) { case LDAP_COMPARE_TRUE: case LDAP_COMPARE_FALSE: a_hasSubordinate = slap_operational_hasSubordinate( rc == LDAP_COMPARE_TRUE ); if ( a_hasSubordinate != NULL ) { for ( ap = &user_entry.e_attrs; *ap; ap = &(*ap)->a_next ); *ap = a_hasSubordinate; } rc = 0; break; default: Debug(LDAP_DEBUG_TRACE, "backsql_search(): " "has_children failed( %d)\n", rc, 0, 0 ); rc = 1; goto next_entry; } } if ( bsi.bsi_flags & BSQL_SF_FILTER_ENTRYUUID ) { a_entryUUID = backsql_operational_entryUUID( bi, eid ); if ( a_entryUUID != NULL ) { if ( ap == NULL ) { ap = &user_entry.e_attrs; } for ( ; *ap; ap = &(*ap)->a_next ); *ap = a_entryUUID; } }#ifdef BACKSQL_SYNCPROV if ( bsi.bsi_flags & BSQL_SF_FILTER_ENTRYCSN ) { a_entryCSN = backsql_operational_entryCSN( op ); if ( a_entryCSN != NULL ) { if ( ap == NULL ) { ap = &user_entry.e_attrs; } for ( ; *ap; ap = &(*ap)->a_next ); *ap = a_entryCSN; } }#endif /* BACKSQL_SYNCPROV */ if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; rs->sr_entry = e; rs->sr_flags = ( e == &user_entry ) ? REP_ENTRY_MODIFIABLE : 0; /* FIXME: need the whole entry (ITS#3480) */ rs->sr_err = send_search_entry( op, rs ); rs->sr_entry = NULL; rs->sr_attrs = NULL; rs->sr_operational_attrs = NULL; switch ( rs->sr_err ) { case LDAP_UNAVAILABLE: /* * FIXME: send_search_entry failed; * better stop */ Debug( LDAP_DEBUG_TRACE, "backsql_search(): " "connection lost\n", 0, 0, 0 ); goto end_of_search; case LDAP_SIZELIMIT_EXCEEDED: goto send_results; } }next_entry:; if ( e == &user_entry ) { backsql_entry_clean( op, &user_entry ); }next_entry2:; }end_of_search:; if ( rs->sr_nentries > 0 ) { rs->sr_ref = rs->sr_v2ref; rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL; } else { rs->sr_err = bsi.bsi_status; }send_results:; if ( rs->sr_err != SLAPD_ABANDON ) { send_ldap_result( op, rs ); } /* cleanup in case of abandon */ for ( ; eid != NULL; eid = backsql_free_entryID( op, eid, eid == &bsi.bsi_base_id ? 0 : 1 ) ) ; backsql_entry_clean( op, &base_entry ); /* in case we got here accidentally */ backsql_entry_clean( op, &user_entry ); if ( rs->sr_v2ref ) { ber_bvarray_free( rs->sr_v2ref ); rs->sr_v2ref = NULL; }#ifdef BACKSQL_SYNCPROV if ( op->o_sync ) { Operation op2 = *op; SlapReply rs2 = { 0 }; Entry e = { 0 }; slap_callback cb = { 0 }; op2.o_tag = LDAP_REQ_ADD; op2.o_bd = select_backend( &op->o_bd->be_nsuffix[0], 0, 0 ); op2.ora_e = &e; op2.o_callback = &cb; e.e_name = op->o_bd->be_suffix[0]; e.e_nname = op->o_bd->be_nsuffix[0]; cb.sc_response = slap_null_cb; op2.o_bd->be_add( &op2, &rs2 ); }#endif /* BACKSQL_SYNCPROV */done:; (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); if ( bsi.bsi_attrs != NULL ) { op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &nbase ) && nbase.bv_val != op->o_req_ndn.bv_val ) { ch_free( nbase.bv_val ); } /* restore scope ... FIXME: this should be done before ANY * frontend call that uses op */ if ( op->ors_scope == BACKSQL_SCOPE_BASE_LIKE ) { op->ors_scope = LDAP_SCOPE_BASE; } Debug( LDAP_DEBUG_TRACE, "<==backsql_search()\n", 0, 0, 0 ); return rs->sr_err;}/* return LDAP_SUCCESS IFF we can retrieve the specified entry. */intbacksql_entry_get( Operation *op, struct berval *ndn, ObjectClass *oc, AttributeDescription *at, int rw, Entry **ent ){ backsql_srch_info bsi = { 0 }; SQLHDBC dbh = SQL_NULL_HDBC; int rc; SlapReply rs = { 0 }; AttributeName anlist[ 2 ]; *ent = NULL; rc = backsql_get_db_conn( op, &dbh ); if ( !dbh ) { return LDAP_OTHER; } if ( at ) { anlist[ 0 ].an_name = at->ad_cname; anlist[ 0 ].an_desc = at; BER_BVZERO( &anlist[ 1 ].an_name ); } bsi.bsi_e = ch_malloc( sizeof( Entry ) ); rc = backsql_init_search( &bsi, ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, &rs, at ? anlist : NULL, BACKSQL_ISF_GET_ENTRY ); if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); } if ( rc == LDAP_SUCCESS ) {#if 0 /* not supported at present */ /* find attribute values */ if ( is_entry_alias( bsi.bsi_e ) ) { Debug( LDAP_DEBUG_ACL, "<= backsql_entry_get: entry is an alias\n", 0, 0, 0 ); rc = LDAP_ALIAS_PROBLEM; goto return_results; }#endif if ( is_entry_referral( bsi.bsi_e ) ) { Debug( LDAP_DEBUG_ACL, "<= backsql_entry_get: entry is a referral\n", 0, 0, 0 ); rc = LDAP_REFERRAL; goto return_results; } if ( oc && !is_entry_objectclass( bsi.bsi_e, oc, 0 ) ) { Debug( LDAP_DEBUG_ACL, "<= backsql_entry_get: " "failed to find objectClass\n", 0, 0, 0 ); rc = LDAP_NO_SUCH_ATTRIBUTE; goto return_results; } *ent = bsi.bsi_e; }return_results:; if ( bsi.bsi_attrs != NULL ) { op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); } if ( rc != LDAP_SUCCESS ) { if ( bsi.bsi_e ) { entry_free( bsi.bsi_e ); } } return rc;}voidbacksql_entry_clean( Operation *op, Entry *e ){ void *ctx; ctx = ldap_pvt_thread_pool_context(); if ( ctx == NULL || ctx != op->o_tmpmemctx ) { if ( !BER_BVISNULL( &e->e_name ) ) { op->o_tmpfree( e->e_name.bv_val, op->o_tmpmemctx ); BER_BVZERO( &e->e_name ); } if ( !BER_BVISNULL( &e->e_nname ) ) { op->o_tmpfree( e->e_nname.bv_val, op->o_tmpmemctx ); BER_BVZERO( &e->e_nname ); } } entry_clean( e );}intbacksql_entry_release( Operation *op, Entry *e, int rw ){ backsql_entry_clean( op, e ); ch_free( e ); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -