Back to index

openldap  2.4.31
Classes | Typedefs | Functions | Variables
slapadd.c File Reference
#include "portable.h"
#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/socket.h>
#include <ac/unistd.h>
#include <lber.h>
#include <ldif.h>
#include <lutil.h>
#include <lutil_meter.h>
#include <sys/stat.h>
#include "slapcommon.h"

Go to the source code of this file.

Classes

struct  Erec
struct  Trec

Typedefs

typedef struct Erec Erec
typedef struct Trec Trec

Functions

static int getrec0 (Erec *erec)
static voidgetrec_thr (void *ctx)
static int getrec (Erec *erec)
int slapadd (int argc, char **argv)

Variables

static char csnbuf [LDAP_PVT_CSNSTR_BUFSIZE]
static Trec trec
static unsigned long sid = SLAP_SYNC_SID_MAX + 1
static int checkvals
static int enable_meter
static lutil_meter_t meter
static const char * progname = "slapadd"
static OperationBuffer opbuf
static char * buf
static int lmax
static ldap_pvt_thread_mutex_t add_mutex
static ldap_pvt_thread_cond_t add_cond
static int add_stop

Class Documentation

struct Erec

Definition at line 45 of file slapadd.c.

Collaboration diagram for Erec:
Class Members
Entry * e
int lineno
int nextline
struct Trec

Definition at line 51 of file slapadd.c.

Collaboration diagram for Trec:
Class Members
Entry * e
int lineno
int nextline
int rc
int ready

Typedef Documentation

typedef struct Erec Erec
typedef struct Trec Trec

Function Documentation

static int getrec ( Erec erec) [static]

Definition at line 306 of file slapadd.c.

{
       int rc;
       if ( slap_tool_thread_max < 2 )
              return getrec0(erec);

       while (!trec.ready)
              ldap_pvt_thread_yield();
       erec->e = trec.e;
       erec->lineno = trec.lineno;
       erec->nextline = trec.nextline;
       trec.ready = 0;
       rc = trec.rc;
       ldap_pvt_thread_mutex_lock( &add_mutex );
       ldap_pvt_thread_mutex_unlock( &add_mutex );
       ldap_pvt_thread_cond_signal( &add_cond );
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int getrec0 ( Erec erec) [static]

Definition at line 80 of file slapadd.c.

{
       const char *text;
       int ldifrc;
       char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
       size_t textlen = sizeof textbuf;
       struct berval csn;
       Operation *op = &opbuf.ob_op;
       op->o_hdr = &opbuf.ob_hdr;

again:
       erec->lineno = erec->nextline+1;
       /* nextline is the line number of the end of the current entry */
       ldifrc = ldif_read_record( ldiffp, &erec->nextline, &buf, &lmax );
       if (ldifrc < 1)
              return ldifrc < 0 ? -1 : 0;
       {
              BackendDB *bd;
              Entry *e;

              if ( erec->lineno < jumpline )
                     goto again;

              e = str2entry2( buf, checkvals );

              if ( enable_meter )
                     lutil_meter_update( &meter,
                                    ftell( ldiffp->fp ),
                                    0);

              if( e == NULL ) {
                     fprintf( stderr, "%s: could not parse entry (line=%d)\n",
                            progname, erec->lineno );
                     return -2;
              }

              /* make sure the DN is not empty */
              if( BER_BVISEMPTY( &e->e_nname ) &&
                     !BER_BVISEMPTY( be->be_nsuffix ))
              {
                     fprintf( stderr, "%s: line %d: "
                            "cannot add entry with empty dn=\"%s\"",
                            progname, erec->lineno, e->e_dn );
                     bd = select_backend( &e->e_nname, nosubordinates );
                     if ( bd ) {
                            BackendDB *bdtmp;
                            int dbidx = 0;
                            LDAP_STAILQ_FOREACH( bdtmp, &backendDB, be_next ) {
                                   if ( bdtmp == bd ) break;
                                   dbidx++;
                            }

                            assert( bdtmp != NULL );
                            
                            fprintf( stderr, "; did you mean to use database #%d (%s)?",
                                   dbidx,
                                   bd->be_suffix[0].bv_val );

                     }
                     fprintf( stderr, "\n" );
                     entry_free( e );
                     return -2;
              }

              /* check backend */
              bd = select_backend( &e->e_nname, nosubordinates );
              if ( bd != be ) {
                     fprintf( stderr, "%s: line %d: "
                            "database #%d (%s) not configured to hold \"%s\"",
                            progname, erec->lineno,
                            dbnum,
                            be->be_suffix[0].bv_val,
                            e->e_dn );
                     if ( bd ) {
                            BackendDB *bdtmp;
                            int dbidx = 0;
                            LDAP_STAILQ_FOREACH( bdtmp, &backendDB, be_next ) {
                                   if ( bdtmp == bd ) break;
                                   dbidx++;
                            }

                            assert( bdtmp != NULL );
                            
                            fprintf( stderr, "; did you mean to use database #%d (%s)?",
                                   dbidx,
                                   bd->be_suffix[0].bv_val );

                     } else {
                            fprintf( stderr, "; no database configured for that naming context" );
                     }
                     fprintf( stderr, "\n" );
                     entry_free( e );
                     return -2;
              }

              if ( slap_tool_entry_check( progname, op, e, erec->lineno, &text, textbuf, textlen ) !=
                     LDAP_SUCCESS ) {
                     entry_free( e );
                     return -2;
              }

              if ( SLAP_LASTMOD(be) ) {
                     time_t now = slap_get_time();
                     char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
                     struct berval vals[ 2 ];

                     struct berval name, timestamp;

                     struct berval nvals[ 2 ];
                     struct berval nname;
                     char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];

                     enum {
                            GOT_NONE = 0x0,
                            GOT_CSN = 0x1,
                            GOT_UUID = 0x2,
                            GOT_ALL = (GOT_CSN|GOT_UUID)
                     } got = GOT_ALL;

                     vals[1].bv_len = 0;
                     vals[1].bv_val = NULL;

                     nvals[1].bv_len = 0;
                     nvals[1].bv_val = NULL;

                     csn.bv_len = ldap_pvt_csnstr( csnbuf, sizeof( csnbuf ), csnsid, 0 );
                     csn.bv_val = csnbuf;

                     timestamp.bv_val = timebuf;
                     timestamp.bv_len = sizeof(timebuf);

                     slap_timestamp( &now, &timestamp );

                     if ( BER_BVISEMPTY( &be->be_rootndn ) ) {
                            BER_BVSTR( &name, SLAPD_ANONYMOUS );
                            nname = name;
                     } else {
                            name = be->be_rootdn;
                            nname = be->be_rootndn;
                     }

                     if( attr_find( e->e_attrs, slap_schema.si_ad_entryUUID )
                            == NULL )
                     {
                            got &= ~GOT_UUID;
                            vals[0].bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) );
                            vals[0].bv_val = uuidbuf;
                            attr_merge_normalize_one( e, slap_schema.si_ad_entryUUID, vals, NULL );
                     }

                     if( attr_find( e->e_attrs, slap_schema.si_ad_creatorsName )
                            == NULL )
                     {
                            vals[0] = name;
                            nvals[0] = nname;
                            attr_merge( e, slap_schema.si_ad_creatorsName, vals, nvals );
                     }

                     if( attr_find( e->e_attrs, slap_schema.si_ad_createTimestamp )
                            == NULL )
                     {
                            vals[0] = timestamp;
                            attr_merge( e, slap_schema.si_ad_createTimestamp, vals, NULL );
                     }

                     if( attr_find( e->e_attrs, slap_schema.si_ad_entryCSN )
                            == NULL )
                     {
                            got &= ~GOT_CSN;
                            vals[0] = csn;
                            attr_merge( e, slap_schema.si_ad_entryCSN, vals, NULL );
                     }

                     if( attr_find( e->e_attrs, slap_schema.si_ad_modifiersName )
                            == NULL )
                     {
                            vals[0] = name;
                            nvals[0] = nname;
                            attr_merge( e, slap_schema.si_ad_modifiersName, vals, nvals );
                     }

                     if( attr_find( e->e_attrs, slap_schema.si_ad_modifyTimestamp )
                            == NULL )
                     {
                            vals[0] = timestamp;
                            attr_merge( e, slap_schema.si_ad_modifyTimestamp, vals, NULL );
                     }

                     if ( SLAP_SINGLE_SHADOW(be) && got != GOT_ALL ) {
                            char buf[SLAP_TEXT_BUFLEN];

                            snprintf( buf, sizeof(buf),
                                   "%s%s%s",
                                   ( !(got & GOT_UUID) ? slap_schema.si_ad_entryUUID->ad_cname.bv_val : "" ),
                                   ( !(got & GOT_CSN) ? "," : "" ),
                                   ( !(got & GOT_CSN) ? slap_schema.si_ad_entryCSN->ad_cname.bv_val : "" ) );

                            Debug( LDAP_DEBUG_ANY, "%s: warning, missing attrs %s from entry dn=\"%s\"\n",
                                   progname, buf, e->e_name.bv_val );
                     }

                     sid = slap_tool_update_ctxcsn_check( progname, e );
              }
              erec->e = e;
       }
       return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void* getrec_thr ( void ctx) [static]

Definition at line 289 of file slapadd.c.

{
       ldap_pvt_thread_mutex_lock( &add_mutex );
       while (!add_stop) {
              trec.rc = getrec0((Erec *)&trec);
              trec.ready = 1;
              while (trec.ready)
                     ldap_pvt_thread_cond_wait( &add_cond, &add_mutex );
              /* eof or read failure */
              if ( trec.rc == 0 || trec.rc == -1 )
                     break;
       }
       ldap_pvt_thread_mutex_unlock( &add_mutex );
       return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int slapadd ( int  argc,
char **  argv 
)

Definition at line 326 of file slapadd.c.

{
       char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
       size_t textlen = sizeof textbuf;
       Erec erec;
       struct berval bvtext;
       ldap_pvt_thread_t thr;
       ID id;

       int ldifrc;
       int rc = EXIT_SUCCESS;

       struct stat stat_buf;

       /* default "000" */
       csnsid = 0;

       if ( isatty (2) ) enable_meter = 1;
       slap_tool_init( progname, SLAPADD, argc, argv );

       if( !be->be_entry_open ||
              !be->be_entry_close ||
              !be->be_entry_put ||
              (update_ctxcsn &&
               (!be->be_dn2id_get ||
                !be->be_entry_get ||
                !be->be_entry_modify)) )
       {
              fprintf( stderr, "%s: database doesn't support necessary operations.\n",
                     progname );
              if ( dryrun ) {
                     fprintf( stderr, "\t(dry) continuing...\n" );

              } else {
                     exit( EXIT_FAILURE );
              }
       }

       checkvals = (slapMode & SLAP_TOOL_QUICK) ? 0 : 1;

       /* do not check values in quick mode */
       if ( slapMode & SLAP_TOOL_QUICK ) {
              if ( slapMode & SLAP_TOOL_VALUE_CHECK ) {
                     fprintf( stderr, "%s: value-check incompatible with quick mode; disabled.\n", progname );
                     slapMode &= ~SLAP_TOOL_VALUE_CHECK;
              }
       }

       /* enforce schema checking unless not disabled */
       if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) {
              SLAP_DBFLAGS(be) &= ~(SLAP_DBFLAG_NO_SCHEMA_CHECK);
       }

       if( !dryrun && be->be_entry_open( be, 1 ) != 0 ) {
              fprintf( stderr, "%s: could not open database.\n",
                     progname );
              exit( EXIT_FAILURE );
       }

       (void)slap_tool_update_ctxcsn_init();

       if ( enable_meter
#ifdef LDAP_DEBUG
              /* tools default to "none" */
              && slap_debug == LDAP_DEBUG_NONE
#endif
              && !fstat ( fileno ( ldiffp->fp ), &stat_buf )
              && S_ISREG(stat_buf.st_mode) ) {
              enable_meter = !lutil_meter_open(
                     &meter,
                     &lutil_meter_text_display,
                     &lutil_meter_linear_estimator,
                     stat_buf.st_size);
       } else {
              enable_meter = 0;
       }

       if ( slap_tool_thread_max > 1 ) {
              ldap_pvt_thread_mutex_init( &add_mutex );
              ldap_pvt_thread_cond_init( &add_cond );
              ldap_pvt_thread_create( &thr, 0, getrec_thr, NULL );
       }

       erec.nextline = 0;
       erec.e = NULL;

       for (;;) {
              ldifrc = getrec( &erec );
              if ( ldifrc < 1 ) {
                     if ( ldifrc == -2 && continuemode )
                            continue;
                     break;
              }

              if ( !dryrun ) {
                     /*
                      * Initialize text buffer
                      */
                     bvtext.bv_len = textlen;
                     bvtext.bv_val = textbuf;
                     bvtext.bv_val[0] = '\0';

                     id = be->be_entry_put( be, erec.e, &bvtext );
                     if( id == NOID ) {
                            fprintf( stderr, "%s: could not add entry dn=\"%s\" "
                                                         "(line=%d): %s\n", progname, erec.e->e_dn,
                                                         erec.lineno, bvtext.bv_val );
                            rc = EXIT_FAILURE;
                            entry_free( erec.e );
                            if( continuemode ) continue;
                            break;
                     }
                     if ( verbose )
                            fprintf( stderr, "added: \"%s\" (%08lx)\n",
                                   erec.e->e_dn, (long) id );
              } else {
                     if ( verbose )
                            fprintf( stderr, "added: \"%s\"\n",
                                   erec.e->e_dn );
              }

              entry_free( erec.e );
       }

       if ( slap_tool_thread_max > 1 ) {
              ldap_pvt_thread_mutex_lock( &add_mutex );
              add_stop = 1;
              trec.ready = 0;
              ldap_pvt_thread_cond_signal( &add_cond );
              ldap_pvt_thread_mutex_unlock( &add_mutex );
              ldap_pvt_thread_join( thr, NULL );
       }

       if ( ldifrc < 0 )
              rc = EXIT_FAILURE;

       bvtext.bv_len = textlen;
       bvtext.bv_val = textbuf;
       bvtext.bv_val[0] = '\0';

       if ( enable_meter ) {
              lutil_meter_update( &meter, ftell( ldiffp->fp ), 1);
              lutil_meter_close( &meter );
       }

       if ( rc == EXIT_SUCCESS ) {
              rc = slap_tool_update_ctxcsn( progname, sid, &bvtext );
       }

       ch_free( buf );

       if ( !dryrun ) {
              if ( enable_meter ) {
                     fprintf( stderr, "Closing DB..." );
              }
              if( be->be_entry_close( be ) ) {
                     rc = EXIT_FAILURE;
              }

              if( be->be_sync ) {
                     be->be_sync( be );
              }
              if ( enable_meter ) {
                     fprintf( stderr, "\n" );
              }
       }

       if ( slap_tool_destroy())
              rc = EXIT_FAILURE;

       return rc;
}

Here is the call graph for this function:


Variable Documentation

Definition at line 70 of file slapadd.c.

Definition at line 69 of file slapadd.c.

int add_stop [static]

Definition at line 71 of file slapadd.c.

char* buf [static]

Definition at line 66 of file slapadd.c.

int checkvals [static]

Definition at line 61 of file slapadd.c.

Definition at line 43 of file slapadd.c.

int enable_meter [static]

Definition at line 62 of file slapadd.c.

int lmax [static]

Definition at line 67 of file slapadd.c.

lutil_meter_t meter [static]

Definition at line 63 of file slapadd.c.

Definition at line 65 of file slapadd.c.

const char* progname = "slapadd" [static]

Definition at line 64 of file slapadd.c.

unsigned long sid = SLAP_SYNC_SID_MAX + 1 [static]

Definition at line 60 of file slapadd.c.

Trec trec [static]

Definition at line 59 of file slapadd.c.