]> git.sur5r.net Git - openldap/commitdiff
implement support for selective iteration in slaptools (ITS#6442)
authorPierangelo Masarati <ando@openldap.org>
Mon, 18 Jan 2010 15:00:40 +0000 (15:00 +0000)
committerPierangelo Masarati <ando@openldap.org>
Mon, 18 Jan 2010 15:00:40 +0000 (15:00 +0000)
19 files changed:
doc/devel/toolargs
doc/man/man8/slapcat.8
doc/man/man8/slapschema.8
servers/slapd/back-bdb/init.c
servers/slapd/back-bdb/proto-bdb.h
servers/slapd/back-bdb/tools.c
servers/slapd/back-ldif/ldif.c
servers/slapd/back-monitor/init.c
servers/slapd/back-null/null.c
servers/slapd/backend.c
servers/slapd/backglue.c
servers/slapd/bconfig.c
servers/slapd/proto-slap.h
servers/slapd/slap.h
servers/slapd/slapcat.c
servers/slapd/slapcommon.c
servers/slapd/slapcommon.h
servers/slapd/slapindex.c
servers/slapd/slapschema.c

index 995e70c5e729c1f163cc9567bd1623b1c9bed605..eae05c953e58dad8618b336ac17974acdfd0664c 100644 (file)
@@ -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:
index eda33474a8b32b57cbce16790f94158375f56a7e..34b4ec005a01e7b2715abdaa82faa119a5057d40 100644 (file)
@@ -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.
index 040be52269cbbcaef3b25aac5ef253c16a78fcd9..bf635b72047b0c0844f4bba964414f67adbc94b0 100644 (file)
@@ -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.
index db51f2a01480281448a1216c3b8e305bafa1d16a..6e7b9bfd914f22e86a657626c79dc56411787d0f 100644 (file)
@@ -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;
index caf9633e92657b846f41bad64237655a83973e0b..93a4ce32f429986771140b57d1fd4f7f56fd983c 100644 (file)
@@ -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;
index 3480290342e0a228ade5acb4352be2f1e573a0c2..ddde4da4f7d4b6d873f3a96f91a013f5e51c03ff 100644 (file)
@@ -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 );
index 40810a33c003270e7e6b4affac34473b2ddf28b0..20a26892b485289a5e2e9bdceff1fa95f3174812 100644 (file)
@@ -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;
index dfd1d861157570b29c008248980109a71feaaab3..73ebb098dd2436f12fb588691c2de6590118f135 100644 (file)
@@ -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;
index ae92e386106fd0da6b5633b60c59d49aedf1dc49..4d4839fc756d0d926513971b6ae81ad5e641e811 100644 (file)
@@ -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;
index 10320083539bce051c684869cd3659fb2bb649dc..de216d09e7812ecd36cd5abf598bbf184018480e 100644 (file)
@@ -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 );
+}
index b7bff32748e4029029f57192a522b27dd96e548b..ee0c556281b01f46138106a6d192726a182118ac 100644 (file)
@@ -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; i<gi->gi_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 )
index b4cc3df3400adff33486ed12cb68535c3eaec3f9..bf13855d9dd72b280db5dd5bad2f2d6287f5b8b5 100644 (file)
@@ -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;
index 62ea62815edd4979654a9191dc84e872c5f55f81..15036dbd86012142651567b25a7a8ee56560f0f2 100644 (file)
@@ -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[]; 
 
 /*
index 5df65f8dd02e144ecfd330737d75f8d8e9a8d47f..3cc7338c9e773521d06479c81ded2ac52b21abd2 100644 (file)
@@ -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;
index a0f1d3c9977502ee137c090b79845584c815bba9..5ddd332b664dea47fed45da3ab4d4558d6a981eb 100644 (file)
@@ -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 );
                }
 
index f3cf2de504bd28649ba9fe3a5e69a15de14b292e..444b4d18d1b0384a50d7f1a9a241ae6c4251cebb 100644 (file)
@@ -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,
+                               "<scope> 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;
 }
+
+
index 56b21cd6481030b839d7891958d990ddf1e3a84f..135d34def04b4b88b1322b151a1e084c58fa4fdf 100644 (file)
@@ -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
index a4e414493ce26d5c82128c0dba68617a53da1449..dc57baaa0518f40e77bc1b55605013bea59da20a 100644 (file)
@@ -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 ) {
index c3b7aaed88b5247fe4887b75a0c99d5d0c40683a..9db8ca81056e57123a8515cd15f417cdb552cd5f 100644 (file)
@@ -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 ) {