]> git.sur5r.net Git - openldap/blob - servers/slapd/slapadd.c
Merge remote branch 'origin/mdb.master' into OPENLDAP_REL_ENG_2_4
[openldap] / servers / slapd / slapadd.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2012 The OpenLDAP Foundation.
5  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
6  * Portions Copyright 2003 IBM Corporation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by Kurt Zeilenga for inclusion
19  * in OpenLDAP Software.  Additional signficant contributors include
20  *    Jong Hyuk Choi
21  *    Pierangelo Masarati
22  */
23
24 #include "portable.h"
25
26 #include <stdio.h>
27
28 #include <ac/stdlib.h>
29
30 #include <ac/ctype.h>
31 #include <ac/string.h>
32 #include <ac/socket.h>
33 #include <ac/unistd.h>
34
35 #include <lber.h>
36 #include <ldif.h>
37 #include <lutil.h>
38 #include <lutil_meter.h>
39 #include <sys/stat.h>
40
41 #include "slapcommon.h"
42
43 static char csnbuf[ LDAP_PVT_CSNSTR_BUFSIZE ];
44
45 typedef struct Erec {
46         Entry *e;
47         int lineno;
48         int nextline;
49 } Erec;
50
51 typedef struct Trec {
52         Entry *e;
53         int lineno;
54         int nextline;
55         int rc;
56         int ready;
57 } Trec;
58
59 static Trec trec;
60 static unsigned long sid = SLAP_SYNC_SID_MAX + 1;
61 static int checkvals;
62 static int enable_meter;
63 static lutil_meter_t meter;
64 static const char *progname = "slapadd";
65 static OperationBuffer opbuf;
66 static char *buf;
67 static int lmax;
68
69 static ldap_pvt_thread_mutex_t add_mutex;
70 static ldap_pvt_thread_cond_t add_cond;
71 static int add_stop;
72
73 /* returns:
74  *      1: got a record
75  *      0: EOF
76  * -1: read failure
77  * -2: parse failure
78  */
79 static int
80 getrec0(Erec *erec)
81 {
82         const char *text;
83         int ldifrc;
84         char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
85         size_t textlen = sizeof textbuf;
86         struct berval csn;
87         Operation *op = &opbuf.ob_op;
88         op->o_hdr = &opbuf.ob_hdr;
89
90 again:
91         erec->lineno = erec->nextline+1;
92         /* nextline is the line number of the end of the current entry */
93         ldifrc = ldif_read_record( ldiffp, &erec->nextline, &buf, &lmax );
94         if (ldifrc < 1)
95                 return ldifrc < 0 ? -1 : 0;
96         {
97                 BackendDB *bd;
98                 Entry *e;
99
100                 if ( erec->lineno < jumpline )
101                         goto again;
102
103                 e = str2entry2( buf, checkvals );
104
105                 if ( enable_meter )
106                         lutil_meter_update( &meter,
107                                          ftell( ldiffp->fp ),
108                                          0);
109
110                 if( e == NULL ) {
111                         fprintf( stderr, "%s: could not parse entry (line=%d)\n",
112                                 progname, erec->lineno );
113                         return -2;
114                 }
115
116                 /* make sure the DN is not empty */
117                 if( BER_BVISEMPTY( &e->e_nname ) &&
118                         !BER_BVISEMPTY( be->be_nsuffix ))
119                 {
120                         fprintf( stderr, "%s: line %d: "
121                                 "cannot add entry with empty dn=\"%s\"",
122                                 progname, erec->lineno, e->e_dn );
123                         bd = select_backend( &e->e_nname, nosubordinates );
124                         if ( bd ) {
125                                 BackendDB *bdtmp;
126                                 int dbidx = 0;
127                                 LDAP_STAILQ_FOREACH( bdtmp, &backendDB, be_next ) {
128                                         if ( bdtmp == bd ) break;
129                                         dbidx++;
130                                 }
131
132                                 assert( bdtmp != NULL );
133                                 
134                                 fprintf( stderr, "; did you mean to use database #%d (%s)?",
135                                         dbidx,
136                                         bd->be_suffix[0].bv_val );
137
138                         }
139                         fprintf( stderr, "\n" );
140                         entry_free( e );
141                         return -2;
142                 }
143
144                 /* check backend */
145                 bd = select_backend( &e->e_nname, nosubordinates );
146                 if ( bd != be ) {
147                         fprintf( stderr, "%s: line %d: "
148                                 "database #%d (%s) not configured to hold \"%s\"",
149                                 progname, erec->lineno,
150                                 dbnum,
151                                 be->be_suffix[0].bv_val,
152                                 e->e_dn );
153                         if ( bd ) {
154                                 BackendDB *bdtmp;
155                                 int dbidx = 0;
156                                 LDAP_STAILQ_FOREACH( bdtmp, &backendDB, be_next ) {
157                                         if ( bdtmp == bd ) break;
158                                         dbidx++;
159                                 }
160
161                                 assert( bdtmp != NULL );
162                                 
163                                 fprintf( stderr, "; did you mean to use database #%d (%s)?",
164                                         dbidx,
165                                         bd->be_suffix[0].bv_val );
166
167                         } else {
168                                 fprintf( stderr, "; no database configured for that naming context" );
169                         }
170                         fprintf( stderr, "\n" );
171                         entry_free( e );
172                         return -2;
173                 }
174
175                 if ( slap_tool_entry_check( progname, op, e, erec->lineno, &text, textbuf, textlen ) !=
176                         LDAP_SUCCESS ) {
177                         entry_free( e );
178                         return -2;
179                 }
180
181                 if ( SLAP_LASTMOD(be) ) {
182                         time_t now = slap_get_time();
183                         char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
184                         struct berval vals[ 2 ];
185
186                         struct berval name, timestamp;
187
188                         struct berval nvals[ 2 ];
189                         struct berval nname;
190                         char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
191
192                         enum {
193                                 GOT_NONE = 0x0,
194                                 GOT_CSN = 0x1,
195                                 GOT_UUID = 0x2,
196                                 GOT_ALL = (GOT_CSN|GOT_UUID)
197                         } got = GOT_ALL;
198
199                         vals[1].bv_len = 0;
200                         vals[1].bv_val = NULL;
201
202                         nvals[1].bv_len = 0;
203                         nvals[1].bv_val = NULL;
204
205                         csn.bv_len = ldap_pvt_csnstr( csnbuf, sizeof( csnbuf ), csnsid, 0 );
206                         csn.bv_val = csnbuf;
207
208                         timestamp.bv_val = timebuf;
209                         timestamp.bv_len = sizeof(timebuf);
210
211                         slap_timestamp( &now, &timestamp );
212
213                         if ( BER_BVISEMPTY( &be->be_rootndn ) ) {
214                                 BER_BVSTR( &name, SLAPD_ANONYMOUS );
215                                 nname = name;
216                         } else {
217                                 name = be->be_rootdn;
218                                 nname = be->be_rootndn;
219                         }
220
221                         if( attr_find( e->e_attrs, slap_schema.si_ad_entryUUID )
222                                 == NULL )
223                         {
224                                 got &= ~GOT_UUID;
225                                 vals[0].bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) );
226                                 vals[0].bv_val = uuidbuf;
227                                 attr_merge_normalize_one( e, slap_schema.si_ad_entryUUID, vals, NULL );
228                         }
229
230                         if( attr_find( e->e_attrs, slap_schema.si_ad_creatorsName )
231                                 == NULL )
232                         {
233                                 vals[0] = name;
234                                 nvals[0] = nname;
235                                 attr_merge( e, slap_schema.si_ad_creatorsName, vals, nvals );
236                         }
237
238                         if( attr_find( e->e_attrs, slap_schema.si_ad_createTimestamp )
239                                 == NULL )
240                         {
241                                 vals[0] = timestamp;
242                                 attr_merge( e, slap_schema.si_ad_createTimestamp, vals, NULL );
243                         }
244
245                         if( attr_find( e->e_attrs, slap_schema.si_ad_entryCSN )
246                                 == NULL )
247                         {
248                                 got &= ~GOT_CSN;
249                                 vals[0] = csn;
250                                 attr_merge( e, slap_schema.si_ad_entryCSN, vals, NULL );
251                         }
252
253                         if( attr_find( e->e_attrs, slap_schema.si_ad_modifiersName )
254                                 == NULL )
255                         {
256                                 vals[0] = name;
257                                 nvals[0] = nname;
258                                 attr_merge( e, slap_schema.si_ad_modifiersName, vals, nvals );
259                         }
260
261                         if( attr_find( e->e_attrs, slap_schema.si_ad_modifyTimestamp )
262                                 == NULL )
263                         {
264                                 vals[0] = timestamp;
265                                 attr_merge( e, slap_schema.si_ad_modifyTimestamp, vals, NULL );
266                         }
267
268                         if ( SLAP_SINGLE_SHADOW(be) && got != GOT_ALL ) {
269                                 char buf[SLAP_TEXT_BUFLEN];
270
271                                 snprintf( buf, sizeof(buf),
272                                         "%s%s%s",
273                                         ( !(got & GOT_UUID) ? slap_schema.si_ad_entryUUID->ad_cname.bv_val : "" ),
274                                         ( !(got & GOT_CSN) ? "," : "" ),
275                                         ( !(got & GOT_CSN) ? slap_schema.si_ad_entryCSN->ad_cname.bv_val : "" ) );
276
277                                 Debug( LDAP_DEBUG_ANY, "%s: warning, missing attrs %s from entry dn=\"%s\"\n",
278                                         progname, buf, e->e_name.bv_val );
279                         }
280
281                         sid = slap_tool_update_ctxcsn_check( progname, e );
282                 }
283                 erec->e = e;
284         }
285         return 1;
286 }
287
288 static void *
289 getrec_thr(void *ctx)
290 {
291         ldap_pvt_thread_mutex_lock( &add_mutex );
292         while (!add_stop) {
293                 trec.rc = getrec0((Erec *)&trec);
294                 trec.ready = 1;
295                 while (trec.ready)
296                         ldap_pvt_thread_cond_wait( &add_cond, &add_mutex );
297                 /* eof or read failure */
298                 if ( trec.rc == 0 || trec.rc == -1 )
299                         break;
300         }
301         ldap_pvt_thread_mutex_unlock( &add_mutex );
302         return NULL;
303 }
304
305 static int ldif_threaded;
306
307 static int
308 getrec(Erec *erec)
309 {
310         int rc;
311         if ( !ldif_threaded )
312                 return getrec0(erec);
313
314         while (!trec.ready)
315                 ldap_pvt_thread_yield();
316         erec->e = trec.e;
317         erec->lineno = trec.lineno;
318         erec->nextline = trec.nextline;
319         trec.ready = 0;
320         rc = trec.rc;
321         ldap_pvt_thread_mutex_lock( &add_mutex );
322         ldap_pvt_thread_mutex_unlock( &add_mutex );
323         ldap_pvt_thread_cond_signal( &add_cond );
324         return rc;
325 }
326
327 int
328 slapadd( int argc, char **argv )
329 {
330         char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
331         size_t textlen = sizeof textbuf;
332         Erec erec;
333         struct berval bvtext;
334         ldap_pvt_thread_t thr;
335         ID id;
336         Entry *prev = NULL;
337
338         int ldifrc;
339         int rc = EXIT_SUCCESS;
340
341         struct stat stat_buf;
342
343         /* default "000" */
344         csnsid = 0;
345
346         if ( isatty (2) ) enable_meter = 1;
347         slap_tool_init( progname, SLAPADD, argc, argv );
348
349         if( !be->be_entry_open ||
350                 !be->be_entry_close ||
351                 !be->be_entry_put ||
352                 (update_ctxcsn &&
353                  (!be->be_dn2id_get ||
354                   !be->be_entry_get ||
355                   !be->be_entry_modify)) )
356         {
357                 fprintf( stderr, "%s: database doesn't support necessary operations.\n",
358                         progname );
359                 if ( dryrun ) {
360                         fprintf( stderr, "\t(dry) continuing...\n" );
361
362                 } else {
363                         exit( EXIT_FAILURE );
364                 }
365         }
366
367         checkvals = (slapMode & SLAP_TOOL_QUICK) ? 0 : 1;
368
369         /* do not check values in quick mode */
370         if ( slapMode & SLAP_TOOL_QUICK ) {
371                 if ( slapMode & SLAP_TOOL_VALUE_CHECK ) {
372                         fprintf( stderr, "%s: value-check incompatible with quick mode; disabled.\n", progname );
373                         slapMode &= ~SLAP_TOOL_VALUE_CHECK;
374                 }
375         }
376
377         /* enforce schema checking unless not disabled */
378         if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) {
379                 SLAP_DBFLAGS(be) &= ~(SLAP_DBFLAG_NO_SCHEMA_CHECK);
380         }
381
382         if( !dryrun && be->be_entry_open( be, 1 ) != 0 ) {
383                 fprintf( stderr, "%s: could not open database.\n",
384                         progname );
385                 exit( EXIT_FAILURE );
386         }
387
388         (void)slap_tool_update_ctxcsn_init();
389
390         if ( enable_meter
391 #ifdef LDAP_DEBUG
392                 /* tools default to "none" */
393                 && slap_debug == LDAP_DEBUG_NONE
394 #endif
395                 && !fstat ( fileno ( ldiffp->fp ), &stat_buf )
396                 && S_ISREG(stat_buf.st_mode) ) {
397                 enable_meter = !lutil_meter_open(
398                         &meter,
399                         &lutil_meter_text_display,
400                         &lutil_meter_linear_estimator,
401                         stat_buf.st_size);
402         } else {
403                 enable_meter = 0;
404         }
405
406         if ( slap_tool_thread_max > 1 ) {
407                 ldap_pvt_thread_mutex_init( &add_mutex );
408                 ldap_pvt_thread_cond_init( &add_cond );
409                 ldap_pvt_thread_create( &thr, 0, getrec_thr, NULL );
410                 ldif_threaded = 1;
411         }
412
413         erec.nextline = 0;
414         erec.e = NULL;
415
416         for (;;) {
417                 ldifrc = getrec( &erec );
418                 if ( ldifrc < 1 ) {
419                         if ( ldifrc == -2 && continuemode )
420                                 continue;
421                         break;
422                 }
423
424                 if ( !dryrun ) {
425                         /*
426                          * Initialize text buffer
427                          */
428                         bvtext.bv_len = textlen;
429                         bvtext.bv_val = textbuf;
430                         bvtext.bv_val[0] = '\0';
431
432                         id = be->be_entry_put( be, erec.e, &bvtext );
433                         if( id == NOID ) {
434                                 fprintf( stderr, "%s: could not add entry dn=\"%s\" "
435                                                                  "(line=%d): %s\n", progname, erec.e->e_dn,
436                                                                  erec.lineno, bvtext.bv_val );
437                                 rc = EXIT_FAILURE;
438                                 if( continuemode ) {
439                                         if ( prev ) entry_free( prev );
440                                         prev = erec.e;
441                                         continue;
442                                 }
443                                 break;
444                         }
445                         if ( verbose )
446                                 fprintf( stderr, "added: \"%s\" (%08lx)\n",
447                                         erec.e->e_dn, (long) id );
448                 } else {
449                         if ( verbose )
450                                 fprintf( stderr, "added: \"%s\"\n",
451                                         erec.e->e_dn );
452                 }
453
454                 if ( prev ) entry_free( prev );
455                 prev = erec.e;
456         }
457
458         if ( ldif_threaded ) {
459                 ldap_pvt_thread_mutex_lock( &add_mutex );
460                 add_stop = 1;
461                 trec.ready = 0;
462                 ldap_pvt_thread_cond_signal( &add_cond );
463                 ldap_pvt_thread_mutex_unlock( &add_mutex );
464                 ldap_pvt_thread_join( thr, NULL );
465         }
466         if ( erec.e ) entry_free( erec.e );
467
468         if ( ldifrc < 0 )
469                 rc = EXIT_FAILURE;
470
471         bvtext.bv_len = textlen;
472         bvtext.bv_val = textbuf;
473         bvtext.bv_val[0] = '\0';
474
475         if ( enable_meter ) {
476                 lutil_meter_update( &meter, ftell( ldiffp->fp ), 1);
477                 lutil_meter_close( &meter );
478         }
479
480         if ( rc == EXIT_SUCCESS ) {
481                 rc = slap_tool_update_ctxcsn( progname, sid, &bvtext );
482         }
483
484         ch_free( buf );
485
486         if ( !dryrun ) {
487                 if ( enable_meter ) {
488                         fprintf( stderr, "Closing DB..." );
489                 }
490                 if( be->be_entry_close( be ) ) {
491                         rc = EXIT_FAILURE;
492                 }
493
494                 if( be->be_sync ) {
495                         be->be_sync( be );
496                 }
497                 if ( enable_meter ) {
498                         fprintf( stderr, "\n" );
499                 }
500         }
501
502         if ( slap_tool_destroy())
503                 rc = EXIT_FAILURE;
504
505         return rc;
506 }
507