From 0d9e140e954f2f753c7cb7f0bc06fffa92b51949 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Thu, 27 Dec 2007 21:08:29 +0000 Subject: [PATCH] allow to workaround size limits when deleting recursively (ITS#5294) --- clients/tools/ldapdelete.c | 78 +++++++++++++++++++++++++++++--------- doc/devel/args | 2 +- doc/man/man1/ldapdelete.1 | 7 ++++ 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/clients/tools/ldapdelete.c b/clients/tools/ldapdelete.c index 635db793fa..12adee45f8 100644 --- a/clients/tools/ldapdelete.c +++ b/clients/tools/ldapdelete.c @@ -51,6 +51,7 @@ static int prune = 0; +static int sizelimit = -1; static int dodelete LDAP_P(( @@ -76,11 +77,13 @@ usage( void ) const char options[] = "r" - "cd:D:e:f:h:H:IMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z"; + "cd:D:e:f:h:H:IMnO:o:p:P:QR:U:vVw:WxX:y:Y:z:Z"; int handle_private_option( int i ) { + int ival; + char *next; switch ( i ) { #if 0 int crit; @@ -115,6 +118,29 @@ handle_private_option( int i ) prune = 1; break; + case 'z': /* size limit */ + if ( strcasecmp( optarg, "none" ) == 0 ) { + sizelimit = 0; + + } else if ( strcasecmp( optarg, "max" ) == 0 ) { + sizelimit = LDAP_MAXINT; + + } else { + ival = strtol( optarg, &next, 10 ); + if ( next == NULL || next[0] != '\0' ) { + fprintf( stderr, + _("Unable to parse size limit \"%s\"\n"), optarg ); + exit( EXIT_FAILURE ); + } + sizelimit = ival; + } + if( sizelimit < 0 || sizelimit > LDAP_MAXINT ) { + fprintf( stderr, _("%s: invalid sizelimit (%d) specified\n"), + prog, sizelimit ); + exit( EXIT_FAILURE ); + } + break; + default: return 0; } @@ -304,27 +330,31 @@ static int dodelete( */ static int deletechildren( LDAP *ld, - const char *dn ) + const char *base ) { LDAPMessage *res, *e; int entries; - int rc; + int rc, srch_rc; static char *attrs[] = { LDAP_NO_ATTRS, NULL }; LDAPControl c, *ctrls[2]; BerElement *ber = NULL; LDAPMessage *res_se; - if ( verbose ) printf ( _("deleting children of: %s\n"), dn ); + if ( verbose ) printf ( _("deleting children of: %s\n"), base ); /* - * Do a one level search at dn for children. For each, delete its children. + * Do a one level search at base for children. For each, delete its children. */ - - rc = ldap_search_ext_s( ld, dn, LDAP_SCOPE_ONELEVEL, NULL, attrs, 1, - NULL, NULL, NULL, -1, &res ); - if ( rc != LDAP_SUCCESS ) { - tool_perror( "ldap_search", rc, NULL, NULL, NULL, NULL ); - return( rc ); +more:; + srch_rc = ldap_search_ext_s( ld, base, LDAP_SCOPE_ONELEVEL, NULL, attrs, 1, + NULL, NULL, NULL, sizelimit, &res ); + switch ( srch_rc ) { + case LDAP_SUCCESS: + case LDAP_SIZELIMIT_EXCEEDED: + break; + default: + tool_perror( "ldap_search", srch_rc, NULL, NULL, NULL, NULL ); + return( srch_rc ); } entries = ldap_count_entries( ld, res ); @@ -373,8 +403,12 @@ static int deletechildren( ldap_msgfree( res ); + if ( srch_rc == LDAP_SIZELIMIT_EXCEEDED ) { + goto more; + } + /* - * Do a one level search at dn for subentry children. + * Do a one level search at base for subentry children. */ if ((ber = ber_alloc_t(LBER_USE_DER)) == NULL) { @@ -394,11 +428,16 @@ static int deletechildren( ctrls[0] = &c; ctrls[1] = NULL; - rc = ldap_search_ext_s( ld, dn, LDAP_SCOPE_ONELEVEL, NULL, attrs, 1, - ctrls, NULL, NULL, -1, &res_se ); - if ( rc != LDAP_SUCCESS ) { - tool_perror( "ldap_search", rc, NULL, NULL, NULL, NULL ); - return( rc ); +more2:; + srch_rc = ldap_search_ext_s( ld, base, LDAP_SCOPE_ONELEVEL, NULL, attrs, 1, + ctrls, NULL, NULL, sizelimit, &res_se ); + switch ( srch_rc ) { + case LDAP_SUCCESS: + case LDAP_SIZELIMIT_EXCEEDED: + break; + default: + tool_perror( "ldap_search", srch_rc, NULL, NULL, NULL, NULL ); + return( srch_rc ); } ber_free( ber, 1 ); @@ -440,5 +479,10 @@ static int deletechildren( } ldap_msgfree( res_se ); + + if ( srch_rc == LDAP_SIZELIMIT_EXCEEDED ) { + goto more2; + } + return rc; } diff --git a/doc/devel/args b/doc/devel/args index 3ee6275350..69316da0f5 100644 --- a/doc/devel/args +++ b/doc/devel/args @@ -1,6 +1,6 @@ Tools ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ldapcompare * DE**HI*K M*OPQR UVWXYZ de *h**k *nop* vwxyz -ldapdelete *CDE**HI*K M*OPQR UVWXYZ cdef*h**k *nop* vwxy +ldapdelete *CDE**HI*K M*OPQR UVWXYZ cdef*h**k *nop* vwxyz ldapmodify *CDE**HI*K M*OPQRS UVWXYZabcde *h**k *nop*r t vwxy ldapmodrdn *CDE**HI*K M*OPQR UVWXYZ cdef*h**k *nop*rs vwxy ldappasswd A*CDE**HI* *O QRS UVWXYZa def*h** * o * s vwxy diff --git a/doc/man/man1/ldapdelete.1 b/doc/man/man1/ldapdelete.1 index ce7b9f950b..d9170da61a 100644 --- a/doc/man/man1/ldapdelete.1 +++ b/doc/man/man1/ldapdelete.1 @@ -53,6 +53,8 @@ ldapdelete \- LDAP delete entry tool [\c .BI \-Y \ mech\fR] [\c +.BI \-z \ sizelimit\fR] +[\c .BR \-Z[Z] ] [\c .IR dn ]... @@ -138,6 +140,11 @@ children, and all their children are deleted down the tree. No verification is done, so if you add this switch, ldapdelete will happily delete large portions of your tree. Use with care. .TP +.BI \-z \ sizelimit +Use \fIsizelimit\fP when searching for children DN to delete, +to circumvent any server-side size limit. Only useful in conjunction +with \-r. +.TP .BI \-O \ security-properties Specify SASL security properties. .TP -- 2.39.5