diff --git a/doc/devel/toolargs b/doc/devel/toolargs index 995e70c5e7..eae05c953e 100644 --- a/doc/devel/toolargs +++ b/doc/devel/toolargs @@ -2,11 +2,11 @@ Tools ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz slapacl D F U X b d f o uv slapadd F S bcd fg j l no q s uvw slapauth F M R U X d f o v -slapcat F abcd fg l no s v +slapcat F H abcd fg l no s v slapdn F N P d f o v slapindex F bcd fg no q t v slappasswd T c h s uv -slapschema F abcd fg l no s v +slapschema F H abcd fg l no s v slaptest F Q d f no uv * General flags: diff --git a/doc/man/man8/slapcat.8 b/doc/man/man8/slapcat.8 index eda33474a8..34b4ec005a 100644 --- a/doc/man/man8/slapcat.8 +++ b/doc/man/man8/slapcat.8 @@ -21,6 +21,8 @@ slapcat \- SLAPD database to LDIF utility [\c .BR \-g ] [\c +.BI \-H URI\fR] +[\c .BI \-l ldif-file\fR] [\c .BI \-n dbnum\fR] @@ -69,6 +71,7 @@ slapcat \-a \\ will dump all but the "ou=People,dc=example,dc=com" subtree of the "dc=example,dc=com" database. +Deprecated; use \fB-H\fP \fIldap:///???(filter)\fP instead. .TP .BI \-b \ suffix Use the specified \fIsuffix\fR to determine which database to @@ -109,6 +112,9 @@ default config file is ignored. disable subordinate gluing. Only the specified database will be processed, and not its glued subordinates (if any). .TP +.B \-H \ URI +use dn, scope and filter from URI to only handle matching entries. +.TP .BI \-l \ ldif-file Write LDIF to specified file instead of standard output. .TP @@ -147,6 +153,7 @@ Implies \fB\-b\fP \fIsubtree-dn\fP if no or .B \-n option is given. +Deprecated; use \fB-H\fP \fIldap:///subtree-dn\fP instead. .TP .B \-v Enable verbose mode. diff --git a/doc/man/man8/slapschema.8 b/doc/man/man8/slapschema.8 index 040be52269..bf635b7204 100644 --- a/doc/man/man8/slapschema.8 +++ b/doc/man/man8/slapschema.8 @@ -21,6 +21,8 @@ slapschema \- SLAPD in-database schema checking utility [\c .BR \-g ] [\c +.BI \-H URI\fR] +[\c .BI \-l error-file\fR] [\c .BI \-n dbnum\fR] @@ -72,6 +74,7 @@ slapschema \-a \\ will check all but the "ou=People,dc=example,dc=com" subtree of the "dc=example,dc=com" database. +Deprecated; use \fB-H\fP \fIldap:///???(filter)\fP instead. .TP .BI \-b \ suffix Use the specified \fIsuffix\fR to determine which database to @@ -112,6 +115,9 @@ default config file is ignored. disable subordinate gluing. Only the specified database will be processed, and not its glued subordinates (if any). .TP +.B \-H \ URI +use dn, scope and filter from URI to only handle matching entries. +.TP .BI \-l \ error-file Write errors to specified file instead of standard output. .TP @@ -149,6 +155,7 @@ Implies \fB\-b\fP \fIsubtree-dn\fP if no nor .B \-n option is given. +Deprecated; use \fB-H\fP \fIldap:///subtree-dn\fP instead. .TP .B \-v Enable verbose mode. diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index db51f2a014..6e7b9bfd91 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -830,7 +830,8 @@ bdb_back_initialize( */ bi->bi_tool_entry_open = bdb_tool_entry_open; bi->bi_tool_entry_close = bdb_tool_entry_close; - bi->bi_tool_entry_first = bdb_tool_entry_next; + bi->bi_tool_entry_first = backend_tool_entry_first; + bi->bi_tool_entry_first_x = bdb_tool_entry_first_x; bi->bi_tool_entry_next = bdb_tool_entry_next; bi->bi_tool_entry_get = bdb_tool_entry_get; bi->bi_tool_entry_put = bdb_tool_entry_put; diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index caf9633e92..93a4ce32f4 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -627,6 +627,7 @@ bdb_trans_backoff( int num_retries ); #define bdb_hasSubordinates BDB_SYMBOL(hasSubordinates) #define bdb_tool_entry_open BDB_SYMBOL(tool_entry_open) #define bdb_tool_entry_close BDB_SYMBOL(tool_entry_close) +#define bdb_tool_entry_first_x BDB_SYMBOL(tool_entry_first_x) #define bdb_tool_entry_next BDB_SYMBOL(tool_entry_next) #define bdb_tool_entry_get BDB_SYMBOL(tool_entry_get) #define bdb_tool_entry_put BDB_SYMBOL(tool_entry_put) @@ -657,6 +658,7 @@ extern BI_has_subordinates bdb_hasSubordinates; /* tools.c */ extern BI_tool_entry_open bdb_tool_entry_open; extern BI_tool_entry_close bdb_tool_entry_close; +extern BI_tool_entry_first_x bdb_tool_entry_first_x; extern BI_tool_entry_next bdb_tool_entry_next; extern BI_tool_entry_get bdb_tool_entry_get; extern BI_tool_entry_put bdb_tool_entry_put; diff --git a/servers/slapd/back-bdb/tools.c b/servers/slapd/back-bdb/tools.c index 3480290342..ddde4da4f7 100644 --- a/servers/slapd/back-bdb/tools.c +++ b/servers/slapd/back-bdb/tools.c @@ -42,6 +42,11 @@ static unsigned nholes; static int index_nattrs; +static struct berval *tool_base; +static int tool_scope; +static Filter *tool_filter; +static Entry *tool_next_entry; + #ifdef BDB_TOOL_IDL_CACHING #define bdb_tool_idl_cmp BDB_SYMBOL(tool_idl_cmp) #define bdb_tool_idl_flush_one BDB_SYMBOL(tool_idl_flush_one) @@ -91,6 +96,9 @@ static void * bdb_tool_trickle_task( void *ctx, void *ptr ); static void * bdb_tool_index_task( void *ctx, void *ptr ); +static int +bdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep ); + int bdb_tool_entry_open( BackendDB *be, int mode ) { @@ -187,6 +195,20 @@ int bdb_tool_entry_close( return 0; } +ID +bdb_tool_entry_first_x( + BackendDB *be, + struct berval *base, + int scope, + Filter *f ) +{ + tool_base = base; + tool_scope = scope; + tool_filter = f; + + return bdb_tool_entry_next( be ); +} + ID bdb_tool_entry_next( BackendDB *be ) { @@ -198,6 +220,7 @@ ID bdb_tool_entry_next( assert( slapMode & SLAP_TOOL_MODE ); assert( bdb != NULL ); +next:; /* Get the header */ data.ulen = data.dlen = sizeof( ehbuf ); data.data = ehbuf; @@ -224,6 +247,47 @@ ID bdb_tool_entry_next( BDB_DISK2ID( key.data, &id ); previd = id; + + if ( tool_filter || tool_base ) { + static Operation op = {0}; + static Opheader ohdr = {0}; + + op.o_hdr = &ohdr; + op.o_bd = be; + op.o_tmpmemctx = NULL; + op.o_tmpmfuncs = &ch_mfuncs; + + if ( tool_next_entry ) { + bdb_entry_release( &op, tool_next_entry, 0 ); + tool_next_entry = NULL; + } + + rc = bdb_tool_entry_get_int( be, id, &tool_next_entry ); + if ( rc == LDAP_NO_SUCH_OBJECT ) { + goto next; + } + + assert( tool_next_entry != NULL ); + +#ifdef BDB_HIER + /* TODO: needed until BDB_HIER is handled accordingly + * in bdb_tool_entry_get_int() */ + if ( tool_base && !dnIsSuffixScope( &tool_next_entry->e_nname, tool_base, tool_scope ) ) + { + bdb_entry_release( &op, tool_next_entry, 0 ); + tool_next_entry = NULL; + goto next; + } +#endif + + if ( tool_filter && test_filter( NULL, tool_next_entry, tool_filter ) != LDAP_COMPARE_TRUE ) + { + bdb_entry_release( &op, tool_next_entry, 0 ); + tool_next_entry = NULL; + goto next; + } + } + return id; } @@ -253,7 +317,8 @@ ID bdb_tool_dn2id_get( return ei->bei_id; } -Entry* bdb_tool_entry_get( BackendDB *be, ID id ) +static int +bdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep ) { Entry *e = NULL; char *dptr; @@ -262,6 +327,12 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id ) assert( be != NULL ); assert( slapMode & SLAP_TOOL_MODE ); + if ( ( tool_filter || tool_base ) && id == previd && tool_next_entry != NULL ) { + *ep = tool_next_entry; + tool_next_entry = NULL; + return LDAP_SUCCESS; + } + if ( id != previd ) { data.ulen = data.dlen = sizeof( ehbuf ); data.data = ehbuf; @@ -269,7 +340,10 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id ) BDB_ID2DISK( id, &nid ); rc = cursor->c_get( cursor, &key, &data, DB_SET ); - if ( rc ) goto done; + if ( rc ) { + rc = LDAP_OTHER; + goto done; + } } /* Get the header */ @@ -279,13 +353,19 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id ) rc = entry_header( &eh ); eoff = eh.data - eh.bv.bv_val; eh.bv.bv_val = dptr; - if ( rc ) goto done; + if ( rc ) { + rc = LDAP_OTHER; + goto done; + } /* Get the size */ data.flags &= ~DB_DBT_PARTIAL; data.ulen = 0; - rc = cursor->c_get( cursor, &key, &data, DB_CURRENT ); - if ( rc != DB_BUFFER_SMALL ) goto done; + rc = cursor->c_get( cursor, &key, &data, DB_CURRENT ); + if ( rc != DB_BUFFER_SMALL ) { + rc = LDAP_OTHER; + goto done; + } /* Allocate a block and retrieve the data */ eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size; @@ -297,8 +377,23 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id ) /* Skip past already parsed nattr/nvals */ eh.data += eoff; - rc = cursor->c_get( cursor, &key, &data, DB_CURRENT ); - if ( rc ) goto done; + rc = cursor->c_get( cursor, &key, &data, DB_CURRENT ); + if ( rc ) { + rc = LDAP_OTHER; + goto done; + } + +#ifndef BDB_HIER + /* TODO: handle BDB_HIER accordingly */ + if ( tool_base != NULL ) { + struct berval ndn; + entry_decode_dn( &eh, NULL, &ndn ); + + if ( !dnIsSuffixScope( &ndn, tool_base, tool_scope ) ) { + return LDAP_NO_SUCH_OBJECT; + } + } +#endif #ifdef SLAP_ZONE_ALLOC /* FIXME: will add ctx later */ @@ -334,7 +429,23 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id ) #endif } done: - return e; + if ( e != NULL ) { + *ep = e; + } + + return rc; +} + +Entry* +bdb_tool_entry_get( BackendDB *be, ID id ) +{ + Entry *e = NULL; + int rc; + + rc = bdb_tool_entry_get_int( be, id, &e ); + if ( rc == LDAP_SUCCESS ) { + return e; + } } static int bdb_tool_next_id( @@ -610,6 +721,9 @@ int bdb_tool_entry_reindex( Operation op = {0}; Opheader ohdr = {0}; + assert( tool_base == NULL ); + assert( tool_filter == NULL ); + Debug( LDAP_DEBUG_ARGS, "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld )\n", (long) id, 0, 0 ); diff --git a/servers/slapd/back-ldif/ldif.c b/servers/slapd/back-ldif/ldif.c index 40810a33c0..20a26892b4 100644 --- a/servers/slapd/back-ldif/ldif.c +++ b/servers/slapd/back-ldif/ldif.c @@ -37,6 +37,9 @@ struct ldif_tool { ID ecount; /* number of entries */ ID ecurrent; /* bi_tool_entry_next() position */ # define ENTRY_BUFF_INCREMENT 500 /* initial entries[] length */ + struct berval *tl_base; + int tl_scope; + Filter *tl_filter; }; /* Per-database data */ @@ -1581,17 +1584,38 @@ ldif_tool_entry_next( BackendDB *be ) { struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool; - if ( tl->ecurrent >= tl->ecount ) - return NOID; - else - return ++tl->ecurrent; + do { + Entry *e = tl->entries[ tl->ecurrent ]; + + if ( tl->ecurrent >= tl->ecount ) { + return NOID; + } + + ++tl->ecurrent; + + if ( tl->tl_base && !dnIsSuffixScope( &e->e_nname, tl->tl_base, tl->tl_scope ) ) { + continue; + } + + if ( tl->tl_filter && test_filter( NULL, e, tl->tl_filter ) != LDAP_COMPARE_TRUE ) { + continue; + } + + break; + } while ( 1 ); + + return tl->ecurrent; } static ID -ldif_tool_entry_first( BackendDB *be ) +ldif_tool_entry_first_x( BackendDB *be, struct berval *base, int scope, Filter *f ) { struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool; + tl->tl_base = base; + tl->tl_scope = scope; + tl->tl_filter = f; + if ( tl->entries == NULL ) { Operation op = {0}; @@ -1740,7 +1764,8 @@ ldif_back_initialize( BackendInfo *bi ) bi->bi_tool_entry_open = ldif_tool_entry_open; bi->bi_tool_entry_close = ldif_tool_entry_close; - bi->bi_tool_entry_first = ldif_tool_entry_first; + bi->bi_tool_entry_first = backend_tool_entry_first; + bi->bi_tool_entry_first_x = ldif_tool_entry_first_x; bi->bi_tool_entry_next = ldif_tool_entry_next; bi->bi_tool_entry_get = ldif_tool_entry_get; bi->bi_tool_entry_put = ldif_tool_entry_put; diff --git a/servers/slapd/back-monitor/init.c b/servers/slapd/back-monitor/init.c index dfd1d86115..73ebb098dd 100644 --- a/servers/slapd/back-monitor/init.c +++ b/servers/slapd/back-monitor/init.c @@ -2061,6 +2061,7 @@ monitor_back_initialize( bi->bi_tool_entry_open = 0; bi->bi_tool_entry_close = 0; bi->bi_tool_entry_first = 0; + bi->bi_tool_entry_first_x = 0; bi->bi_tool_entry_next = 0; bi->bi_tool_entry_get = 0; bi->bi_tool_entry_put = 0; diff --git a/servers/slapd/back-null/null.c b/servers/slapd/back-null/null.c index ae92e38610..4d4839fc75 100644 --- a/servers/slapd/back-null/null.c +++ b/servers/slapd/back-null/null.c @@ -254,6 +254,12 @@ null_tool_entry_close( BackendDB *be ) return 0; } +static ID +null_tool_entry_first_x( BackendDB *be, struct berval *base, int scope, Filter *f ) +{ + return NOID; +} + static ID null_tool_entry_next( BackendDB *be ) { @@ -392,7 +398,8 @@ null_back_initialize( BackendInfo *bi ) bi->bi_tool_entry_open = null_tool_entry_open; bi->bi_tool_entry_close = null_tool_entry_close; - bi->bi_tool_entry_first = null_tool_entry_next; + bi->bi_tool_entry_first = backend_tool_entry_first; + bi->bi_tool_entry_first_x = null_tool_entry_first_x; bi->bi_tool_entry_next = null_tool_entry_next; bi->bi_tool_entry_get = null_tool_entry_get; bi->bi_tool_entry_put = null_tool_entry_put; diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 1032008353..de216d09e7 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -1965,3 +1965,12 @@ int backend_operational( Operation *op, SlapReply *rs ) return rc; } +/* helper that calls the bi_tool_entry_first_x() variant with default args; + * use to initialize a backend's bi_tool_entry_first() when appropriate + */ +ID +backend_tool_entry_first( BackendDB *be ) +{ + return be->bd_info->bi_tool_entry_first_x( be, + NULL, LDAP_SCOPE_DEFAULT, NULL ); +} diff --git a/servers/slapd/backglue.c b/servers/slapd/backglue.c index b7bff32748..ee0c556281 100644 --- a/servers/slapd/backglue.c +++ b/servers/slapd/backglue.c @@ -735,6 +735,10 @@ glue_entry_release_rw ( return rc; } +static struct berval *glue_base; +static int glue_scope; +static Filter *glue_filter; + static ID glue_tool_entry_first ( BackendDB *b0 @@ -785,6 +789,66 @@ glue_tool_entry_first ( return rc; } +static ID +glue_tool_entry_first_x ( + BackendDB *b0, + struct berval *base, + int scope, + Filter *f +) +{ + slap_overinst *on = glue_tool_inst( b0->bd_info ); + glueinfo *gi = on->on_bi.bi_private; + int i; + ID rc; + + glue_base = base; + glue_scope = scope; + glue_filter = f; + + /* If we're starting from scratch, start at the most general */ + if (!glueBack) { + if ( toolDB.be_entry_open && toolDB.be_entry_first_x ) { + glueBack = &toolDB; + } else { + for (i = gi->gi_nodes-1; i >= 0; i--) { + if (gi->gi_n[i].gn_be->be_entry_open && + gi->gi_n[i].gn_be->be_entry_first_x) + { + glueBack = gi->gi_n[i].gn_be; + break; + } + } + } + } + if (!glueBack || !glueBack->be_entry_open || !glueBack->be_entry_first_x || + glueBack->be_entry_open (glueBack, glueMode) != 0) + return NOID; + + rc = glueBack->be_entry_first_x (glueBack, + glue_base, glue_scope, glue_filter); + while ( rc == NOID ) { + if ( glueBack && glueBack->be_entry_close ) + glueBack->be_entry_close (glueBack); + for (i=0; igi_nodes; i++) { + if (gi->gi_n[i].gn_be == glueBack) + break; + } + if (i == 0) { + glueBack = GLUEBACK_DONE; + break; + } else { + glueBack = gi->gi_n[i-1].gn_be; + rc = glue_tool_entry_first_x (b0, + glue_base, glue_scope, glue_filter); + if ( glueBack == GLUEBACK_DONE ) { + break; + } + } + } + return rc; +} + static ID glue_tool_entry_next ( BackendDB *b0 @@ -813,7 +877,15 @@ glue_tool_entry_next ( break; } else { glueBack = gi->gi_n[i-1].gn_be; - rc = glue_tool_entry_first (b0); + if ( glue_base || glue_filter ) { + /* using entry_first_x() */ + rc = glue_tool_entry_first_x (b0, + glue_base, glue_scope, glue_filter); + + } else { + /* using entry_first() */ + rc = glue_tool_entry_first (b0); + } if ( glueBack == GLUEBACK_DONE ) { break; } @@ -1012,6 +1084,9 @@ glue_db_init( oi->oi_bi.bi_tool_entry_close = glue_tool_entry_close; if ( bi->bi_tool_entry_first ) oi->oi_bi.bi_tool_entry_first = glue_tool_entry_first; + /* FIXME: check whether all support bi_tool_entry_first_x() ? */ + if ( bi->bi_tool_entry_first_x ) + oi->oi_bi.bi_tool_entry_first_x = glue_tool_entry_first_x; if ( bi->bi_tool_entry_next ) oi->oi_bi.bi_tool_entry_next = glue_tool_entry_next; if ( bi->bi_tool_entry_get ) diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index b4cc3df340..bf13855d9d 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -6803,10 +6803,30 @@ config_tool_entry_first( BackendDB *be ) CfBackInfo *cfb = be->be_private; BackendInfo *bi = cfb->cb_db.bd_info; - if ( bi && bi->bi_tool_entry_first ) + if ( bi && bi->bi_tool_entry_first ) { return bi->bi_tool_entry_first( &cfb->cb_db ); - else - return NOID; + } + if ( bi && bi->bi_tool_entry_first_x ) { + return bi->bi_tool_entry_first_x( &cfb->cb_db, + NULL, LDAP_SCOPE_DEFAULT, NULL ); + } + return NOID; +} + +static ID +config_tool_entry_first_x( + BackendDB *be, + struct berval *base, + int scope, + Filter *f ) +{ + CfBackInfo *cfb = be->be_private; + BackendInfo *bi = cfb->cb_db.bd_info; + + if ( bi && bi->bi_tool_entry_first_x ) { + return bi->bi_tool_entry_first_x( &cfb->cb_db, base, scope, f ); + } + return NOID; } static ID @@ -7053,6 +7073,7 @@ config_back_initialize( BackendInfo *bi ) bi->bi_tool_entry_open = config_tool_entry_open; bi->bi_tool_entry_close = config_tool_entry_close; bi->bi_tool_entry_first = config_tool_entry_first; + bi->bi_tool_entry_first_x = config_tool_entry_first_x; bi->bi_tool_entry_next = config_tool_entry_next; bi->bi_tool_entry_get = config_tool_entry_get; bi->bi_tool_entry_put = config_tool_entry_put; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 62ea62815e..15036dbd86 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -428,6 +428,8 @@ LDAP_SLAPD_F (int) backend_operational LDAP_P(( SlapReply *rs )); +LDAP_SLAPD_F (ID) backend_tool_entry_first LDAP_P(( BackendDB *be )); + LDAP_SLAPD_V(BackendInfo) slap_binfo[]; /* diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 5df65f8dd0..3cc7338c9e 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1795,6 +1795,7 @@ struct BackendDB { #define be_entry_open bd_info->bi_tool_entry_open #define be_entry_close bd_info->bi_tool_entry_close #define be_entry_first bd_info->bi_tool_entry_first +#define be_entry_first_x bd_info->bi_tool_entry_first_x #define be_entry_next bd_info->bi_tool_entry_next #define be_entry_reindex bd_info->bi_tool_entry_reindex #define be_entry_get bd_info->bi_tool_entry_get @@ -2165,6 +2166,7 @@ typedef BI_conn_func BI_connection_destroy; typedef int (BI_tool_entry_open) LDAP_P(( BackendDB *be, int mode )); typedef int (BI_tool_entry_close) LDAP_P(( BackendDB *be )); typedef ID (BI_tool_entry_first) LDAP_P(( BackendDB *be )); +typedef ID (BI_tool_entry_first_x) LDAP_P(( BackendDB *be, struct berval *base, int scope, Filter *f )); typedef ID (BI_tool_entry_next) LDAP_P(( BackendDB *be )); typedef Entry* (BI_tool_entry_get) LDAP_P(( BackendDB *be, ID id )); typedef ID (BI_tool_entry_put) LDAP_P(( BackendDB *be, Entry *e, @@ -2264,7 +2266,8 @@ struct BackendInfo { /* hooks for slap tools */ BI_tool_entry_open *bi_tool_entry_open; BI_tool_entry_close *bi_tool_entry_close; - BI_tool_entry_first *bi_tool_entry_first; + BI_tool_entry_first *bi_tool_entry_first; /* deprecated */ + BI_tool_entry_first_x *bi_tool_entry_first_x; BI_tool_entry_next *bi_tool_entry_next; BI_tool_entry_get *bi_tool_entry_get; BI_tool_entry_put *bi_tool_entry_put; diff --git a/servers/slapd/slapcat.c b/servers/slapd/slapcat.c index a0f1d3c997..5ddd332b66 100644 --- a/servers/slapd/slapcat.c +++ b/servers/slapd/slapcat.c @@ -47,9 +47,13 @@ slapcat( int argc, char **argv ) int rc = EXIT_SUCCESS; Operation op = {0}; const char *progname = "slapcat"; + int requestBSF; + int doBSF = 0; slap_tool_init( progname, SLAPCAT, argc, argv ); + requestBSF = ( sub_ndn.bv_len || filter ); + #ifdef SIGPIPE (void) SIGNAL( SIGPIPE, slapcat_sig ); #endif @@ -61,7 +65,7 @@ slapcat( int argc, char **argv ) if( !be->be_entry_open || !be->be_entry_close || - !be->be_entry_first || + !( be->be_entry_first_x || be->be_entry_first ) || !be->be_entry_next || !be->be_entry_get ) { @@ -77,9 +81,22 @@ slapcat( int argc, char **argv ) } op.o_bd = be; - for ( id = be->be_entry_first( be ); - id != NOID; - id = be->be_entry_next( be ) ) + if ( !requestBSF && be->be_entry_first ) { + id = be->be_entry_first( be ); + + } else { + if ( be->be_entry_first_x ) { + id = be->be_entry_first_x( be, + sub_ndn.bv_len ? &sub_ndn : NULL, scope, filter ); + + } else { + assert( be->be_entry_first != NULL ); + doBSF = 1; + id = be->be_entry_first( be ); + } + } + + for ( ; id != NOID; id = be->be_entry_next( be ) ) { char *data; int len; @@ -96,20 +113,24 @@ slapcat( int argc, char **argv ) break; } - if( sub_ndn.bv_len && !dnIsSuffix( &e->e_nname, &sub_ndn ) ) { - be_entry_release_r( &op, e ); - continue; - } - - if( filter != NULL ) { - int rc = test_filter( NULL, e, filter ); - if( rc != LDAP_COMPARE_TRUE ) { + if ( doBSF ) { + if ( sub_ndn.bv_len && !dnIsSuffixScope( &e->e_nname, &sub_ndn, scope ) ) + { be_entry_release_r( &op, e ); continue; } + + + if ( filter != NULL ) { + int rc = test_filter( NULL, e, filter ); + if ( rc != LDAP_COMPARE_TRUE ) { + be_entry_release_r( &op, e ); + continue; + } + } } - if( verbose ) { + if ( verbose ) { printf( "# id=%08lx\n", (long) id ); } diff --git a/servers/slapd/slapcommon.c b/servers/slapd/slapcommon.c index f3cf2de504..444b4d18d1 100644 --- a/servers/slapd/slapcommon.c +++ b/servers/slapd/slapcommon.c @@ -80,7 +80,7 @@ usage( int tool, const char *progname ) case SLAPCAT: options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]" - " [-l ldiffile] [-a filter] [-s subtree]\n"; + " [-l ldiffile] [-a filter] [-s subtree] [-H url]\n"; break; case SLAPDN: @@ -97,7 +97,7 @@ usage( int tool, const char *progname ) case SLAPSCHEMA: options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]" - " [-l errorfile] [-a filter] [-s subtree]\n"; + " [-l errorfile] [-a filter] [-s subtree] [-H url]\n"; break; } @@ -247,13 +247,15 @@ slap_tool_init( leakfilename = NULL; #endif + scope = LDAP_SCOPE_DEFAULT; + switch( tool ) { case SLAPADD: options = "b:cd:f:F:gj:l:n:o:qsS:uvw"; break; case SLAPCAT: - options = "a:b:cd:f:F:gl:n:o:s:v"; + options = "a:b:cd:f:F:gH:l:n:o:s:v"; mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; break; @@ -263,7 +265,7 @@ slap_tool_init( break; case SLAPSCHEMA: - options = "a:b:cd:f:F:gl:n:o:s:v"; + options = "a:b:cd:f:F:gH:l:n:o:s:v"; mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; break; @@ -344,6 +346,52 @@ slap_tool_init( use_glue = 0; break; + case 'H': { + LDAPURLDesc *ludp; + int rc; + + rc = ldap_url_parse_ext( optarg, &ludp, + LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_NOEMPTY_DN ); + if ( rc != LDAP_URL_SUCCESS ) { + usage( tool, progname ); + } + + /* don't accept host, port, attrs, extensions */ + if ( ldap_pvt_url_scheme2proto( ludp->lud_scheme ) != LDAP_PROTO_TCP ) { + usage( tool, progname ); + } + + if ( ludp->lud_host != NULL ) { + usage( tool, progname ); + } + + if ( ludp->lud_port != 0 ) { + usage( tool, progname ); + } + + if ( ludp->lud_attrs != NULL ) { + usage( tool, progname ); + } + + if ( ludp->lud_exts != NULL ) { + usage( tool, progname ); + } + + if ( ludp->lud_dn != NULL && ludp->lud_dn[0] != '\0' ) { + subtree = ludp->lud_dn; + ludp->lud_dn = NULL; + } + + if ( ludp->lud_filter != NULL && ludp->lud_filter[0] != '\0' ) { + filterstr = ludp->lud_filter; + ludp->lud_filter = NULL; + } + + scope = ludp->lud_scope; + + ldap_free_urldesc( ludp ); + } break; + case 'j': /* jump to linenumber */ if ( lutil_atoi( &jumpline, optarg ) ) { usage( tool, progname ); @@ -743,6 +791,17 @@ get_db: } } + if ( scope != LDAP_SCOPE_DEFAULT && BER_BVISNULL( &sub_ndn ) ) { + if ( be && be->be_nsuffix ) { + ber_dupbv( &sub_ndn, be->be_nsuffix ); + + } else { + fprintf( stderr, + " needs a DN or a valid database\n" ); + exit( EXIT_FAILURE ); + } + } + startup:; if ( be ) { BackendDB *bdtmp; @@ -833,3 +892,5 @@ int slap_tool_destroy( void ) } return rc; } + + diff --git a/servers/slapd/slapcommon.h b/servers/slapd/slapcommon.h index 56b21cd648..135d34def0 100644 --- a/servers/slapd/slapcommon.h +++ b/servers/slapd/slapcommon.h @@ -43,8 +43,9 @@ typedef struct tool_vars { int tv_nosubordinates; int tv_dryrun; int tv_jumpline; - Filter *tv_filter; struct berval tv_sub_ndn; + int tv_scope; + Filter *tv_filter; struct LDIFFP *tv_ldiffp; struct berval tv_baseDN; struct berval tv_authcDN; @@ -76,8 +77,9 @@ extern tool_vars tool_globals; #define continuemode tool_globals.tv_continuemode #define nosubordinates tool_globals.tv_nosubordinates #define dryrun tool_globals.tv_dryrun -#define filter tool_globals.tv_filter #define sub_ndn tool_globals.tv_sub_ndn +#define scope tool_globals.tv_scope +#define filter tool_globals.tv_filter #define ldiffp tool_globals.tv_ldiffp #define baseDN tool_globals.tv_baseDN #define authcDN tool_globals.tv_authcDN diff --git a/servers/slapd/slapindex.c b/servers/slapd/slapindex.c index a4e414493c..dc57baaa05 100644 --- a/servers/slapd/slapindex.c +++ b/servers/slapd/slapindex.c @@ -43,7 +43,7 @@ slapindex( int argc, char **argv ) if( !be->be_entry_open || !be->be_entry_close || - !be->be_entry_first || + !( be->be_entry_first || be->be_entry_first_x ) || !be->be_entry_next || !be->be_entry_reindex ) { @@ -77,11 +77,16 @@ slapindex( int argc, char **argv ) progname ); exit( EXIT_FAILURE ); } - - for ( id = be->be_entry_first( be ); - id != NOID; - id = be->be_entry_next( be ) ) - { + + if ( be->be_entry_first ) { + id = be->be_entry_first( be ); + + } else { + assert( be->be_entry_first_x != NULL ); + id = be->be_entry_first_x( be, NULL, LDAP_SCOPE_DEFAULT, NULL ); + } + + for ( ; id != NOID; id = be->be_entry_next( be ) ) { int rtn; if( verbose ) { diff --git a/servers/slapd/slapschema.c b/servers/slapd/slapschema.c index c3b7aaed88..9db8ca8105 100644 --- a/servers/slapd/slapschema.c +++ b/servers/slapd/slapschema.c @@ -50,9 +50,13 @@ slapschema( int argc, char **argv ) OperationBuffer opbuf; Operation *op = NULL; void *thrctx; + int requestBSF = 0; + int doBSF = 0; slap_tool_init( progname, SLAPCAT, argc, argv ); + requestBSF = ( sub_ndn.bv_len || filter ); + #ifdef SIGPIPE (void) SIGNAL( SIGPIPE, slapcat_sig ); #endif @@ -64,7 +68,7 @@ slapschema( int argc, char **argv ) if( !be->be_entry_open || !be->be_entry_close || - !be->be_entry_first || + !( be->be_entry_first || be->be_entry_first_x ) || !be->be_entry_next || !be->be_entry_get ) { @@ -85,10 +89,23 @@ slapschema( int argc, char **argv ) op->o_tmpmemctx = NULL; op->o_bd = be; - for ( id = be->be_entry_first( be ); - id != NOID; - id = be->be_entry_next( be ) ) - { + + if ( !requestBSF && be->be_entry_first ) { + id = be->be_entry_first( be ); + + } else { + if ( be->be_entry_first_x ) { + id = be->be_entry_first_x( be, + sub_ndn.bv_len ? &sub_ndn : NULL, scope, filter ); + + } else { + assert( be->be_entry_first != NULL ); + doBSF = 1; + id = be->be_entry_first( be ); + } + } + + for ( ; id != NOID; id = be->be_entry_next( be ) ) { Entry* e; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof(textbuf); @@ -105,17 +122,21 @@ slapschema( int argc, char **argv ) break; } - if( sub_ndn.bv_len && !dnIsSuffix( &e->e_nname, &sub_ndn ) ) { - be_entry_release_r( op, e ); - continue; - } - - if( filter != NULL ) { - int rc = test_filter( NULL, e, filter ); - if( rc != LDAP_COMPARE_TRUE ) { + if ( doBSF ) { + if ( sub_ndn.bv_len && !dnIsSuffixScope( &e->e_nname, &sub_ndn, scope ) ) + { be_entry_release_r( op, e ); continue; } + + + if ( filter != NULL ) { + int rc = test_filter( NULL, e, filter ); + if ( rc != LDAP_COMPARE_TRUE ) { + be_entry_release_r( op, e ); + continue; + } + } } if( verbose ) {