]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/slapcat.c
Merge remote-tracking branch 'origin/mdb.master' into OPENLDAP_REL_ENG_2_4
[openldap] / servers / slapd / slapcat.c
index 7daeaa645a185f0c25be1699e3cbad8cc2c07793..713b908287d9d3dddafc8e7c9ee9ad6f557f759f 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2004 The OpenLDAP Foundation.
+ * Copyright 1998-2014 The OpenLDAP Foundation.
  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
  * Portions Copyright 2003 IBM Corporation.
  * All rights reserved.
 #include <ac/string.h>
 
 #include "slapcommon.h"
+#include "ldif.h"
+
+static volatile sig_atomic_t gotsig;
+
+static RETSIGTYPE
+slapcat_sig( int sig )
+{
+       gotsig=1;
+}
 
 int
 slapcat( int argc, char **argv )
@@ -38,12 +47,25 @@ 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
+#ifdef SIGHUP
+       (void) SIGNAL( SIGHUP, slapcat_sig );
+#endif
+       (void) SIGNAL( SIGINT, slapcat_sig );
+       (void) SIGNAL( SIGTERM, slapcat_sig );
+
        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 )
        {
@@ -58,54 +80,75 @@ slapcat( int argc, char **argv )
                exit( EXIT_FAILURE );
        }
 
-       for ( id = be->be_entry_first( be );
-               id != NOID;
-               id = be->be_entry_next( be ) )
+       op.o_bd = 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;
-               Entry* e = be->be_entry_get( be, id );
-               op.o_bd = be;
+               Entry* e;
 
+               if ( gotsig )
+                       break;
+
+               e = be->be_entry_get( be, id );
                if ( e == NULL ) {
                        printf("# no data for entry id=%08lx\n\n", (long) id );
                        rc = EXIT_FAILURE;
-                       if( continuemode ) continue;
-                       break;
-               }
-
-               if( sub_ndn.bv_len && !dnIsSuffix( &e->e_nname, &sub_ndn ) ) {
-                       be_entry_release_r( &op, e );
-                       continue;
-               }
+                       if ( continuemode == 0 ) {
+                               break;
 
-               if( filter != NULL ) {
-                       int rc = test_filter( NULL, e, filter );
-                       if( rc != LDAP_COMPARE_TRUE ) {
-                               be_entry_release_r( &op, e );
+                       } else if ( continuemode == 1 ) {
                                continue;
                        }
-               }
 
-               if ( retrieve_ctxcsn == 0 ) {
-                       if ( is_entry_syncProviderSubentry( e ) ) {
-                               be_entry_release_r( &op, e );
-                               continue;
+                       /* this is a last resort: linearly scan all ids
+                        * trying to recover as much as possible (ITS#6482) */
+                       while ( ++id != NOID ) {
+                               e = be->be_entry_get( be, id );
+                               if ( e != NULL ) break;
+                               printf("# no data for entry id=%08lx\n\n", (long) id );
                        }
+
+                       if ( e == NULL ) break;
                }
 
-               if ( retrieve_synccookie == 0 ) {
-                       if ( is_entry_syncConsumerSubentry( e ) ) {
+               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 );
                }
 
-               data = entry2str( e, &len );
+               data = entry2str_wrap( e, &len, ldif_wrap );
                be_entry_release_r( &op, e );
 
                if ( data == NULL ) {
@@ -115,12 +158,18 @@ slapcat( int argc, char **argv )
                        break;
                }
 
-               fputs( data, ldiffp );
-               fputs( "\n", ldiffp );
+               if ( fputs( data, ldiffp->fp ) == EOF ||
+                       fputs( "\n", ldiffp->fp ) == EOF ) {
+                       fprintf(stderr, "%s: error writing output.\n",
+                               progname);
+                       rc = EXIT_FAILURE;
+                       break;
+               }
        }
 
        be->be_entry_close( be );
 
-       slap_tool_destroy();
+       if ( slap_tool_destroy())
+               rc = EXIT_FAILURE;
        return rc;
 }