1 /* $OpenLDAP: pkg/ldap/servers/slapd/slapadd.c,v 1.36.2.7 2008/04/14 21:15:47 quanah Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2008 The OpenLDAP Foundation.
5 * Portions Copyright 1998-2003 Kurt D. Zeilenga.
6 * Portions Copyright 2003 IBM Corporation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
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>.
18 * This work was initially developed by Kurt Zeilenga for inclusion
19 * in OpenLDAP Software. Additional signficant contributors include
28 #include <ac/stdlib.h>
31 #include <ac/string.h>
32 #include <ac/socket.h>
33 #include <ac/unistd.h>
39 #include "slapcommon.h"
41 static char csnbuf
[ LDAP_LUTIL_CSNSTR_BUFSIZE
];
42 static char maxcsnbuf
[ LDAP_LUTIL_CSNSTR_BUFSIZE
* ( SLAP_SYNC_SID_MAX
+ 1 ) ];
45 slapadd( int argc
, char **argv
)
49 char textbuf
[SLAP_TEXT_BUFLEN
] = { '\0' };
50 size_t textlen
= sizeof textbuf
;
51 const char *progname
= "slapadd";
54 struct berval maxcsn
[ SLAP_SYNC_SID_MAX
+ 1 ];
60 OperationBuffer opbuf
;
67 int rc
= EXIT_SUCCESS
;
73 slap_tool_init( progname
, SLAPADD
, argc
, argv
);
75 memset( &opbuf
, 0, sizeof(opbuf
) );
77 op
->o_hdr
= &opbuf
.ob_hdr
;
79 if( !be
->be_entry_open
||
80 !be
->be_entry_close
||
85 !be
->be_entry_modify
)) )
87 fprintf( stderr
, "%s: database doesn't support necessary operations.\n",
90 fprintf( stderr
, "\t(dry) continuing...\n" );
97 checkvals
= (slapMode
& SLAP_TOOL_QUICK
) ? 0 : 1;
102 /* enforce schema checking unless not disabled */
103 if ( (slapMode
& SLAP_TOOL_NO_SCHEMA_CHECK
) == 0) {
104 SLAP_DBFLAGS(be
) &= ~(SLAP_DBFLAG_NO_SCHEMA_CHECK
);
107 if( !dryrun
&& be
->be_entry_open( be
, 1 ) != 0 ) {
108 fprintf( stderr
, "%s: could not open database.\n",
110 exit( EXIT_FAILURE
);
113 if ( update_ctxcsn
) {
114 maxcsn
[ 0 ].bv_val
= maxcsnbuf
;
115 for ( sid
= 1; sid
<= SLAP_SYNC_SID_MAX
; sid
++ ) {
116 maxcsn
[ sid
].bv_val
= maxcsn
[ sid
- 1 ].bv_val
+ LDAP_LUTIL_CSNSTR_BUFSIZE
;
117 maxcsn
[ sid
].bv_len
= 0;
121 /* nextline is the line number of the end of the current entry */
122 for( lineno
=1; ldif_read_record( ldiffp
, &nextline
, &buf
, &lmax
);
123 lineno
=nextline
+1 ) {
126 if ( lineno
< jumpline
)
129 e
= str2entry2( buf
, checkvals
);
132 * Initialize text buffer
134 bvtext
.bv_len
= textlen
;
135 bvtext
.bv_val
= textbuf
;
136 bvtext
.bv_val
[0] = '\0';
139 fprintf( stderr
, "%s: could not parse entry (line=%d)\n",
142 if( continuemode
) continue;
146 /* make sure the DN is not empty */
147 if( BER_BVISEMPTY( &e
->e_nname
) &&
148 !BER_BVISEMPTY( be
->be_nsuffix
)) {
149 fprintf( stderr
, "%s: empty dn=\"%s\" (line=%d)\n",
150 progname
, e
->e_dn
, lineno
);
153 if( continuemode
) continue;
158 if( select_backend( &e
->e_nname
, nosubordinates
)
161 fprintf( stderr
, "%s: line %d: "
162 "database (%s) not configured to hold \"%s\"\n",
164 be
? be
->be_suffix
[0].bv_val
: "<none>",
166 fprintf( stderr
, "%s: line %d: "
167 "database (%s) not configured to hold \"%s\"\n",
169 be
? be
->be_nsuffix
[0].bv_val
: "<none>",
173 if( continuemode
) continue;
178 Attribute
*oc
= attr_find( e
->e_attrs
,
179 slap_schema
.si_ad_objectClass
);
182 fprintf( stderr
, "%s: dn=\"%s\" (line=%d): %s\n",
183 progname
, e
->e_dn
, lineno
,
184 "no objectClass attribute");
187 if( continuemode
) continue;
194 if ( (slapMode
& SLAP_TOOL_NO_SCHEMA_CHECK
) == 0) {
195 rc
= entry_schema_check( op
, e
, NULL
, manage
, 1,
196 &text
, textbuf
, textlen
);
198 if( rc
!= LDAP_SUCCESS
) {
199 fprintf( stderr
, "%s: dn=\"%s\" (line=%d): (%d) %s\n",
200 progname
, e
->e_dn
, lineno
, rc
, text
);
203 if( continuemode
) continue;
210 if ( SLAP_LASTMOD(be
) ) {
211 time_t now
= slap_get_time();
212 char uuidbuf
[ LDAP_LUTIL_UUIDSTR_BUFSIZE
];
213 struct berval vals
[ 2 ];
215 struct berval name
, timestamp
;
217 struct berval nvals
[ 2 ];
219 char timebuf
[ LDAP_LUTIL_GENTIME_BUFSIZE
];
222 vals
[1].bv_val
= NULL
;
225 nvals
[1].bv_val
= NULL
;
227 csn
.bv_len
= lutil_csnstr( csnbuf
, sizeof( csnbuf
), csnsid
, 0 );
230 timestamp
.bv_val
= timebuf
;
231 timestamp
.bv_len
= sizeof(timebuf
);
233 slap_timestamp( &now
, ×tamp
);
235 if ( BER_BVISEMPTY( &be
->be_rootndn
) ) {
236 BER_BVSTR( &name
, SLAPD_ANONYMOUS
);
239 name
= be
->be_rootdn
;
240 nname
= be
->be_rootndn
;
243 if( attr_find( e
->e_attrs
, slap_schema
.si_ad_entryUUID
)
246 vals
[0].bv_len
= lutil_uuidstr( uuidbuf
, sizeof( uuidbuf
) );
247 vals
[0].bv_val
= uuidbuf
;
248 attr_merge_normalize_one( e
, slap_schema
.si_ad_entryUUID
, vals
, NULL
);
251 if( attr_find( e
->e_attrs
, slap_schema
.si_ad_creatorsName
)
256 attr_merge( e
, slap_schema
.si_ad_creatorsName
, vals
, nvals
);
259 if( attr_find( e
->e_attrs
, slap_schema
.si_ad_createTimestamp
)
263 attr_merge( e
, slap_schema
.si_ad_createTimestamp
, vals
, NULL
);
266 if( attr_find( e
->e_attrs
, slap_schema
.si_ad_entryCSN
)
270 attr_merge( e
, slap_schema
.si_ad_entryCSN
, vals
, NULL
);
273 if( attr_find( e
->e_attrs
, slap_schema
.si_ad_modifiersName
)
278 attr_merge( e
, slap_schema
.si_ad_modifiersName
, vals
, nvals
);
281 if( attr_find( e
->e_attrs
, slap_schema
.si_ad_modifyTimestamp
)
285 attr_merge( e
, slap_schema
.si_ad_modifyTimestamp
, vals
, NULL
);
288 if ( update_ctxcsn
) {
291 attr
= attr_find( e
->e_attrs
, slap_schema
.si_ad_entryCSN
);
292 assert( attr
!= NULL
);
294 rc_sid
= slap_parse_csn_sid( &attr
->a_nvals
[ 0 ] );
296 Debug( LDAP_DEBUG_ANY
, "%s: could not "
297 "extract SID from entryCSN=%s\n",
298 progname
, attr
->a_nvals
[ 0 ].bv_val
, 0 );
301 assert( rc_sid
<= SLAP_SYNC_SID_MAX
);
303 sid
= (unsigned)rc_sid
;
304 if ( maxcsn
[ sid
].bv_len
!= 0 ) {
306 value_match( &match
, slap_schema
.si_ad_entryCSN
,
307 slap_schema
.si_ad_entryCSN
->ad_type
->sat_ordering
,
308 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX
,
309 &maxcsn
[ sid
], &attr
->a_nvals
[0], &text
);
314 strcpy( maxcsn
[ sid
].bv_val
, attr
->a_nvals
[0].bv_val
);
315 maxcsn
[ sid
].bv_len
= attr
->a_nvals
[0].bv_len
;
322 id
= be
->be_entry_put( be
, e
, &bvtext
);
324 fprintf( stderr
, "%s: could not add entry dn=\"%s\" "
325 "(line=%d): %s\n", progname
, e
->e_dn
,
326 lineno
, bvtext
.bv_val
);
329 if( continuemode
) continue;
333 fprintf( stderr
, "added: \"%s\" (%08lx)\n",
334 e
->e_dn
, (long) id
);
337 fprintf( stderr
, "added: \"%s\"\n",
344 bvtext
.bv_len
= textlen
;
345 bvtext
.bv_val
= textbuf
;
346 bvtext
.bv_val
[0] = '\0';
348 if ( rc
== EXIT_SUCCESS
&& update_ctxcsn
&& !dryrun
&& sid
!= SLAP_SYNC_SID_MAX
+ 1 ) {
349 ctxcsn_id
= be
->be_dn2id_get( be
, be
->be_nsuffix
);
350 if ( ctxcsn_id
== NOID
) {
351 fprintf( stderr
, "%s: context entry is missing\n", progname
);
354 ctxcsn_e
= be
->be_entry_get( be
, ctxcsn_id
);
355 if ( ctxcsn_e
!= NULL
) {
356 Entry
*e
= entry_dup( ctxcsn_e
);
358 attr
= attr_find( e
->e_attrs
, slap_schema
.si_ad_contextCSN
);
364 for ( i
= 0; !BER_BVISNULL( &attr
->a_nvals
[ i
] ); i
++ ) {
367 rc_sid
= slap_parse_csn_sid( &attr
->a_nvals
[ i
] );
369 Debug( LDAP_DEBUG_ANY
,
370 "%s: unable to extract SID "
371 "from #%d contextCSN=%s\n",
373 attr
->a_nvals
[ i
].bv_val
);
377 assert( rc_sid
<= SLAP_SYNC_SID_MAX
);
379 sid
= (unsigned)rc_sid
;
381 if ( maxcsn
[ sid
].bv_len
== 0 ) {
385 value_match( &match
, slap_schema
.si_ad_entryCSN
,
386 slap_schema
.si_ad_entryCSN
->ad_type
->sat_ordering
,
387 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX
,
388 &maxcsn
[ sid
], &attr
->a_nvals
[i
], &text
);
394 AC_MEMCPY( maxcsn
[ sid
].bv_val
,
395 attr
->a_nvals
[ i
].bv_val
,
396 attr
->a_nvals
[ i
].bv_len
);
397 maxcsn
[ sid
].bv_val
[ attr
->a_nvals
[ i
].bv_len
] = '\0';
398 maxcsn
[ sid
].bv_len
= attr
->a_nvals
[ i
].bv_len
;
403 if ( attr
->a_nvals
!= attr
->a_vals
) {
404 ber_bvarray_free( attr
->a_nvals
);
406 attr
->a_nvals
= NULL
;
407 ber_bvarray_free( attr
->a_vals
);
416 for ( sid
= 0; sid
<= SLAP_SYNC_SID_MAX
; sid
++ ) {
417 if ( maxcsn
[ sid
].bv_len
) {
418 attr_merge_one( e
, slap_schema
.si_ad_contextCSN
,
419 &maxcsn
[ sid
], NULL
);
423 ctxcsn_id
= be
->be_entry_modify( be
, e
, &bvtext
);
424 if( ctxcsn_id
== NOID
) {
425 fprintf( stderr
, "%s: could not modify ctxcsn\n",
428 } else if ( verbose
) {
429 fprintf( stderr
, "modified: \"%s\" (%08lx)\n",
430 e
->e_dn
, (long) ctxcsn_id
);
441 if( be
->be_entry_close( be
) ) {