summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoriko Hosoi <nhosoi@redhat.com>2010-07-15 13:33:28 -0700
committerNoriko Hosoi <nhosoi@redhat.com>2010-07-15 13:33:28 -0700
commit50bb2ee6676e10cdda704982dfa831efa4011037 (patch)
tree508e082c6e9a3e130e4e74f53db80fb3cb865ed2
parentb7888ed0511a93156943be4e45bf1e261804f641 (diff)
downloadds-50bb2ee6676e10cdda704982dfa831efa4011037.tar.gz
ds-50bb2ee6676e10cdda704982dfa831efa4011037.tar.xz
ds-50bb2ee6676e10cdda704982dfa831efa4011037.zip
612771 - RHDS 8.1/389 v1.2.5 accepts 2 identical entries withDirectory_Server_8_2_Candidate_20100715
different DN formats https://bugzilla.redhat.com/show_bug.cgi?id=612771 Fix Description: This patch fixes the upgradednformat utility to eliminate the duplicated DNs found in the upgrading period. Assuming DN: attr0=value0,attr1=value1,...,attrn=valuen exists in the DB and another identical DN is found, the second DN is renamed to nsuniqueid=<uuid>+attr0=value0,attr1=value1,...,attrn=valuen , where the <uuid> is the unique id assigned to the entry when the entry is added to the server. The modification is logged in the error log. In addition, there was a bug to handle multi-valued RDNs in slapi_dn_normalize_ext. In case multi-valued RDN appears with DN value (e.g., nsuniqueid=<uuid>+cn=uid\=<uid>\,o\=<org>,dc=<dc>), it was not normalized properly. Introduced second rdn_av_stack (subinitial_rdn_av_stack) for the nested DN value. See also: http://directory.fedoraproject.org/wiki/Upgrade_to_New_DN_Format#Another_Upgrade_Scenario
-rw-r--r--ldap/admin/src/scripts/70upgradednformat.pl22
-rw-r--r--ldap/servers/slapd/back-ldbm/ancestorid.c3
-rw-r--r--ldap/servers/slapd/back-ldbm/back-ldbm.h11
-rw-r--r--ldap/servers/slapd/back-ldbm/dblayer.c2
-rw-r--r--ldap/servers/slapd/back-ldbm/import-threads.c186
-rw-r--r--ldap/servers/slapd/back-ldbm/import.c24
-rw-r--r--ldap/servers/slapd/back-ldbm/import.h1
-rw-r--r--ldap/servers/slapd/back-ldbm/ldif2ldbm.c17
-rw-r--r--ldap/servers/slapd/dn.c61
-rw-r--r--ldap/servers/slapd/entry.c53
-rw-r--r--ldap/servers/slapd/slap.h1
-rw-r--r--ldap/servers/slapd/slapi-plugin.h9
-rw-r--r--ldap/servers/slapd/slapi-private.h1
13 files changed, 299 insertions, 92 deletions
diff --git a/ldap/admin/src/scripts/70upgradednformat.pl b/ldap/admin/src/scripts/70upgradednformat.pl
index 894a0887..100a318c 100644
--- a/ldap/admin/src/scripts/70upgradednformat.pl
+++ b/ldap/admin/src/scripts/70upgradednformat.pl
@@ -15,15 +15,21 @@ use File::Copy;
sub runinst {
my ($inf, $inst, $dseldif, $conn) = @_;
- # First, check if the server is up or down.
- if ($conn->isa("Mozilla::LDAP::Conn")) {
- # The server is up, we do nothing.
- return ();
- }
-
my @errs;
my $config = "cn=config";
+ my $config_entry = $conn->search($config, "base", "(cn=*)");
+ if (!$config_entry) {
+ return ("error_no_configuration_entry", $!);
+ }
+ # First, check if the server is up or down.
+ my $rundir = $config_entry->getValues('nsslapd-rundir');
+
+ # Check if the server is up or not
+ my $pidfile = $rundir . "/" . $inst . ".pid";
+ if (-e $pidfile) {
+ return (); # server is running; do nothing.
+ }
my $mappingtree = "cn=mapping tree,cn=config";
my $ldbmbase = "cn=ldbm database,cn=plugins,cn=config";
@@ -62,10 +68,6 @@ sub runinst {
$mtentry = $conn->nextEntry();
}
- my $config_entry = $conn->search($config, "base", "(cn=*)", 0, ("nsslapd-instancedir"));
- if (!$config_entry) {
- return ("error_no_configuration_entry", $!);
- }
my $instancedir = $config_entry->{"nsslapd-instancedir"}[0];
my $upgradednformat = $instancedir . "/upgradednformat";
diff --git a/ldap/servers/slapd/back-ldbm/ancestorid.c b/ldap/servers/slapd/back-ldbm/ancestorid.c
index 59d77223..8f641452 100644
--- a/ldap/servers/slapd/back-ldbm/ancestorid.c
+++ b/ldap/servers/slapd/back-ldbm/ancestorid.c
@@ -397,7 +397,8 @@ static int ldbm_ancestorid_new_idl_create_index(backend *be)
ai_aid->ai_indexmask |= INDEX_OFFLINE;
/* Open the ancestorid index file */
- ret = dblayer_get_index_file(be, ai_aid, &db_aid, DBOPEN_CREATE);
+ ret = dblayer_get_index_file(be, ai_aid, &db_aid,
+ DBOPEN_CREATE|DBOPEN_TRUNCATE);
if (ret != 0) {
ldbm_nasty(sourcefile,13050,ret);
goto out;
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h
index 1bf9a035..efcf03f9 100644
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
@@ -755,7 +755,18 @@ typedef struct _back_search_result_set
/* flag: open_flag for dblayer_get_index_file -> dblayer_open_file */
#define DBOPEN_CREATE 0x1 /* oprinary mode: create a db file if needed */
+#define DBOPEN_TRUNCATE 0x2 /* oprinary mode: truncate a db file if needed */
/* whether we call fat lock or not [608146] */
#define SERIALLOCK(li) (li->li_fat_lock)
+
+/*
+ * 0: SUCCESS
+ * libdb returns negative error codes
+ * Linux errno's < 140, for now
+ * Chose any positive value other than the above values.
+ * Being used to specify duplicated DN is found in entrydn or entryrdn.
+ */
+#define LDBM_ERROR_FOUND_DUPDN 9999
+
#endif /* _back_ldbm_h_ */
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 27a4f6f4..23da61ff 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -2792,6 +2792,8 @@ int dblayer_open_file(backend *be, char* indexname, int open_flag, struct attrin
open_flags = DB_THREAD;
if (open_flag & DBOPEN_CREATE)
open_flags |= DB_CREATE;
+ if (open_flag & DBOPEN_TRUNCATE)
+ open_flags |= DB_TRUNCATE;
if (!ppDB)
goto out;
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c
index 32fcf467..859f6c39 100644
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
@@ -547,7 +547,7 @@ void import_producer(void *param)
curr_lineno, curr_filename);
if (e) {
slapi_entry_free(e);
- }
+ }
job->skipped++;
continue;
@@ -978,7 +978,7 @@ upgradedn_free_list(struct upgradedn_attr **ud_list)
slapi_ch_free((void **)&ptr);
ptr = next;
}
- *ud_list = NULL;
+ *ud_list = NULL;
return;
}
@@ -1011,8 +1011,8 @@ upgradedn_add_to_list(struct upgradedn_attr **ud_list,
* deleted attribute list e_deleted_attrs.
*
* If FLAG_UPGRADEDNFORMAT is set, worker_threads for indexing DN syntax
- * attributes are brought up. Foreman thread updates entrydn index
- * as well as the entry itself in the id2entry.db#.
+ * attributes (+ cn & ou) are brought up. Foreman thread updates entrydn
+ * index as well as the entry itself in the id2entry.db#.
*
* Note: QUIT state for info->state is introduced for DRYRUN mode to
* distinguish the intentional QUIT (found the dn upgrade candidate)
@@ -1142,7 +1142,7 @@ upgradedn_producer(void *param)
ecopy = (char *)slapi_ch_malloc(data.dsize + 1);
memcpy(ecopy, data.dptr, data.dsize);
*(ecopy + data.dsize) = '\0';
- e = slapi_str2entry(data.data, 0);
+ e = slapi_str2entry(data.data, SLAPI_STR2ENTRY_USE_OBSOLETE_DNFORMAT);
if ( NULL == e ) {
if (job->task) {
slapi_task_log_notice(job->task,
@@ -1274,7 +1274,7 @@ upgradedn_producer(void *param)
skipit = 0;
for (ud_ptr = ud_list; ud_ptr; ud_ptr = ud_ptr->ud_next) {
- /* Move the current value to e_deleted_attrs. */
+ /* Move the current value to e_aux_attrs. */
ud_attr = attrlist_find(e->e_attrs, ud_ptr->ud_type);
if (ud_attr) {
if (0 == strcmp(ud_ptr->ud_type, "entrydn")) {
@@ -1304,24 +1304,24 @@ upgradedn_producer(void *param)
break;
}
}
- attrlist_add(&e->e_deleted_attrs, ud_attr);
+ attrlist_add(&e->e_aux_attrs, ud_attr);
} else {
/* We have to normalize the orignal string to generate
the key in the index.
*/
- a = attrlist_find(e->e_deleted_attrs, ud_ptr->ud_type);
+ a = attrlist_find(e->e_aux_attrs, ud_ptr->ud_type);
if (!a) {
a = slapi_attr_new();
slapi_attr_init(a, ud_ptr->ud_type);
} else {
- a = attrlist_remove(&e->e_deleted_attrs,
+ a = attrlist_remove(&e->e_aux_attrs,
ud_ptr->ud_type);
}
slapi_dn_normalize_case_original(ud_ptr->ud_value);
value = slapi_value_new_string(ud_ptr->ud_value);
slapi_attr_add_value(a, value);
slapi_value_free(&value);
- attrlist_add(&e->e_deleted_attrs, a);
+ attrlist_add(&e->e_aux_attrs, a);
}
}
}
@@ -1475,7 +1475,7 @@ import_wait_for_space_in_fifo(ImportJob *job, size_t new_esize)
}
/* helper function for the foreman: */
-static int foreman_do_parentid(ImportJob *job, struct backentry *entry,
+static int foreman_do_parentid(ImportJob *job, FifoItem *fi,
struct attrinfo *parentid_ai)
{
backend *be = job->inst->inst_be;
@@ -1483,11 +1483,44 @@ static int foreman_do_parentid(ImportJob *job, struct backentry *entry,
Slapi_Attr *attr = NULL;
int idl_disposition = 0;
int ret = 0;
+ struct backentry *entry = fi->entry;
+
+ if (job->flags & FLAG_UPGRADEDNFORMAT) {
+ /* Get the parentid attribute value from deleted attr list */
+ Slapi_Value *value = NULL;
+ Slapi_Attr *pid_to_del =
+ attrlist_remove(&entry->ep_entry->e_aux_attrs, "parentid");
+ if (pid_to_del) {
+ /* Delete it. */
+ ret = slapi_attr_first_value(pid_to_del, &value);
+ if (ret < 0) {
+ import_log_notice(job,
+ "Error: retrieving parentid value (error %d)",
+ ret);
+ } else {
+ const struct berval *bval =
+ slapi_value_get_berval((const Slapi_Value *)value);
+ ret = index_addordel_string(be, "parentid",
+ bval->bv_val, entry->ep_id,
+ BE_INDEX_DEL|BE_INDEX_EQUALITY|BE_INDEX_NORMALIZED,
+ NULL);
+ if (ret) {
+ import_log_notice(job,
+ "Error: deleting %s from parentid index "
+ "(error %d: %s)",
+ bval->bv_val, ret, dblayer_strerror(ret));
+ return ret;
+ }
+ }
+ slapi_attr_free(&pid_to_del);
+ }
+ }
if (slapi_entry_attr_find(entry->ep_entry, "parentid", &attr) == 0) {
svals = attr_get_present_values(attr);
- ret = index_addordel_values_ext_sv(be, "parentid", svals, NULL, entry->ep_id,
- BE_INDEX_ADD, NULL, &idl_disposition, NULL);
+ ret = index_addordel_values_ext_sv(be, "parentid", svals, NULL,
+ entry->ep_id, BE_INDEX_ADD,
+ NULL, &idl_disposition, NULL);
if (idl_disposition != IDL_INSERT_NORMAL) {
char *attr_value = slapi_value_get_berval(svals[0])->bv_val;
ID parent_id = atol(attr_value);
@@ -1510,19 +1543,20 @@ static int foreman_do_parentid(ImportJob *job, struct backentry *entry,
}
/* helper function for the foreman: */
-static int foreman_do_entrydn(ImportJob *job, FifoItem *fi)
+static int
+foreman_do_entrydn(ImportJob *job, FifoItem *fi)
{
backend *be = job->inst->inst_be;
struct berval bv;
int err = 0, ret = 0;
IDList *IDL;
+ struct backentry *entry = fi->entry;
if (job->flags & FLAG_UPGRADEDNFORMAT) {
/* Get the entrydn attribute value from deleted attr list */
Slapi_Value *value = NULL;
Slapi_Attr *entrydn_to_del =
- attrlist_remove(&fi->entry->ep_entry->e_deleted_attrs, "entrydn");
-
+ attrlist_remove(&entry->ep_entry->e_aux_attrs, "entrydn");
if (entrydn_to_del) {
/* Delete it. */
ret = slapi_attr_first_value(entrydn_to_del, &value);
@@ -1534,8 +1568,7 @@ static int foreman_do_entrydn(ImportJob *job, FifoItem *fi)
const struct berval *bval =
slapi_value_get_berval((const Slapi_Value *)value);
ret = index_addordel_string(be, "entrydn",
- bval->bv_val,
- fi->entry->ep_id,
+ bval->bv_val, entry->ep_id,
BE_INDEX_DEL|BE_INDEX_EQUALITY|BE_INDEX_NORMALIZED,
NULL);
if (ret) {
@@ -1551,7 +1584,7 @@ static int foreman_do_entrydn(ImportJob *job, FifoItem *fi)
}
/* insert into the entrydn index */
- bv.bv_val = (void*)backentry_get_ndn(fi->entry); /* jcm - Had to cast away const */
+ bv.bv_val = (void*)backentry_get_ndn(entry); /* jcm - Had to cast away const */
bv.bv_len = strlen(bv.bv_val);
/* We need to check here whether the DN is already present in
@@ -1565,14 +1598,24 @@ static int foreman_do_entrydn(ImportJob *job, FifoItem *fi)
if (job->flags & FLAG_UPGRADEDNFORMAT) {
/*
* In the UPGRADEDNFORMAT case, if entrydn value exists,
- * that means entrydn is not upgraded. And it is normal.
- * We could add entrydn only when the value is not found in the db.
+ * that means either 1) entrydn is not upgraded (ID == entry->ep_id)
+ * or 2) a duplicated entry is found (ID != entry->ep_id).
+ * (1) is normal. For (2), need to return a specific error
+ * LDBM_ERROR_FOUND_DUPDN.
+ * Otherwise, add entrydn to the entrydn index file.
*/
if (IDL) {
+ ID id = idl_firstid(IDL); /* entrydn is a single attr */
idl_free(IDL);
+ if (id != entry->ep_id) { /* case (2) */
+ import_log_notice(job, "Duplicated entrydn detected: \"%s\": "
+ "Entry ID: (%d, %d)",
+ bv.bv_val, id, entry->ep_id);
+ return LDBM_ERROR_FOUND_DUPDN;
+ }
} else {
ret = index_addordel_string(be, "entrydn",
- bv.bv_val, fi->entry->ep_id,
+ bv.bv_val, entry->ep_id,
BE_INDEX_ADD|BE_INDEX_NORMALIZED, NULL);
if (ret) {
import_log_notice(job, "Error writing entrydn index "
@@ -1587,7 +1630,7 @@ static int foreman_do_entrydn(ImportJob *job, FifoItem *fi)
/* IMPOSTER ! Get thee hence... */
import_log_notice(job, "WARNING: Skipping duplicate entry "
"\"%s\" found at line %d of file \"%s\"",
- slapi_entry_get_dn(fi->entry->ep_entry),
+ slapi_entry_get_dn(entry->ep_entry),
fi->line, fi->filename);
idl_free(IDL);
/* skip this one */
@@ -1595,7 +1638,7 @@ static int foreman_do_entrydn(ImportJob *job, FifoItem *fi)
job->skipped++;
return -1; /* skip to next entry */
}
- ret = index_addordel_string(be, "entrydn", bv.bv_val, fi->entry->ep_id,
+ ret = index_addordel_string(be, "entrydn", bv.bv_val, entry->ep_id,
BE_INDEX_ADD|BE_INDEX_NORMALIZED, NULL);
if (ret) {
import_log_notice(job, "Error writing entrydn index "
@@ -1678,6 +1721,11 @@ void import_foreman(void *param)
/* first, fill in any operational attributes */
/* add_op_attrs wants a pblock for some reason. */
+ if (job->flags & FLAG_UPGRADEDNFORMAT) {
+ /* Upgrade dn format may alter the DIT structure. */
+ /* It requires a special treatment for that. */
+ parent_status = IMPORT_ADD_OP_ATTRS_SAVE_OLD_PID;
+ }
if (add_op_attrs(pb, inst->inst_li, fi->entry, &parent_status) != 0) {
import_log_notice(job, "ERROR: Could not add op attrs to "
"entry ending at line %d of file \"%s\"",
@@ -1720,10 +1768,85 @@ void import_foreman(void *param)
/* insert into the entrydn index */
ret = foreman_do_entrydn(job, fi);
- if (ret == -1)
+ if (ret == -1) {
goto cont; /* skip entry */
- if (ret != 0)
+ } else if ((job->flags & FLAG_UPGRADEDNFORMAT) &&
+ (LDBM_ERROR_FOUND_DUPDN == ret)) {
+ /*
+ * Duplicated DN is detected.
+ *
+ * Rename <DN> to nsuniqueid=<uuid>+<DN>
+ * E.g., uid=tuser,dc=example,dc=com ==>
+ * nsuniqueid=<uuid>+uid=tuser,dc=example,dc=com
+ *
+ * Note: FLAG_UPGRADEDNFORMAT only.
+ */
+ Slapi_Attr *orig_entrydn = NULL;
+ Slapi_Attr *new_entrydn = slapi_attr_new();
+ Slapi_Attr *nsuniqueid = NULL;
+ char *uuidstr = NULL;
+ char *new_dn = NULL;
+ char *orig_dn =
+ slapi_ch_strdup(slapi_entry_get_dn(fi->entry->ep_entry));
+ struct berval *vals[2];
+ struct berval val;
+ int rc = 0;
+ nsuniqueid = attrlist_find(fi->entry->ep_entry->e_attrs,
+ "nsuniqueid");
+ if (nsuniqueid) {
+ Slapi_Value *uival = NULL;
+ rc = slapi_attr_first_value(nsuniqueid, &uival);
+ uuidstr = slapi_value_get_string(uival);
+ } else {
+ import_log_notice(job, "ERROR: Failed to get nsUniqueId "
+ "of the duplicated entry %s; "
+ "Entry ID: %d",
+ orig_dn, fi->entry->ep_id);
+ goto cont;
+ }
+ new_dn = slapi_create_dn_string("nsuniqueid=%s+%s",
+ uuidstr, orig_dn);
+ /* releasing original dn */
+ slapi_sdn_done(&fi->entry->ep_entry->e_sdn);
+ /* setting new dn; pass in */
+ slapi_sdn_init_dn_passin(&fi->entry->ep_entry->e_sdn, new_dn);
+
+ /* Replacing entrydn attribute value */
+ orig_entrydn = attrlist_remove(&fi->entry->ep_entry->e_attrs,
+ "entrydn");
+ /* released in forman_do_entrydn */
+ attrlist_add(&fi->entry->ep_entry->e_aux_attrs, orig_entrydn);
+
+ /* Setting new entrydn attribute value */
+ slapi_attr_init(new_entrydn, "entrydn");
+ valueset_add_string(&new_entrydn->a_present_values,
+ /* new_dn: duped in valueset_add_string */
+ (const char *)new_dn,
+ CSN_TYPE_UNKNOWN, NULL);
+ attrlist_add(&fi->entry->ep_entry->e_attrs, new_entrydn);
+
+ /* Try foreman_do_entrydn, again. */
+ ret = foreman_do_entrydn(job, fi);
+ if (ret) {
+ import_log_notice(job, "ERROR: Failed to rename duplicated "
+ "DN %s to %s; Entry ID: %d",
+ orig_dn, new_dn, fi->entry->ep_id);
+ slapi_ch_free_string(&orig_dn);
+ if (-1 == ret) {
+ goto cont; /* skip entry */
+ } else {
+ goto error;
+ }
+ } else {
+ import_log_notice(job, "WARNING: Duplicated entry %s is "
+ "renamed to %s; Entry ID: %d",
+ orig_dn, new_dn, fi->entry->ep_id);
+ slapi_ch_free_string(&orig_dn);
+ }
+
+ } else if (ret != 0) {
goto error;
+ }
}
if (job->flags & FLAG_ABORT) {
@@ -1764,17 +1887,14 @@ void import_foreman(void *param)
goto error;
}
- if (!(job->flags & FLAG_UPGRADEDNFORMAT) && /* Upgrade dn format mode
- does not need to update
- parentid index */
- !slapi_entry_flag_is_set(fi->entry->ep_entry,
- SLAPI_ENTRY_FLAG_TOMBSTONE)) {
+ if (!slapi_entry_flag_is_set(fi->entry->ep_entry,
+ SLAPI_ENTRY_FLAG_TOMBSTONE)) {
/* parentid index
* (we have to do this here, because the parentID is dependent on
* looking up by entrydn.)
* Only add to the parent index if the entry is not a tombstone.
*/
- ret = foreman_do_parentid(job, fi->entry, parentid_ai);
+ ret = foreman_do_parentid(job, fi, parentid_ai);
if (ret != 0)
goto error;
@@ -1954,7 +2074,7 @@ void import_worker(void *param)
Slapi_Value *value = NULL;
const struct berval *bval = NULL;
Slapi_Attr *key_to_del =
- attrlist_remove(&fi->entry->ep_entry->e_deleted_attrs,
+ attrlist_remove(&fi->entry->ep_entry->e_aux_attrs,
info->index_info->name);
if (key_to_del) {
diff --git a/ldap/servers/slapd/back-ldbm/import.c b/ldap/servers/slapd/back-ldbm/import.c
index 8b66705f..dde03db3 100644
--- a/ldap/servers/slapd/back-ldbm/import.c
+++ b/ldap/servers/slapd/back-ldbm/import.c
@@ -262,11 +262,25 @@ static int import_attr_callback(void *node, void *param)
* attribute type. (except entrydn -- taken care below) */
int rc = 0;
Slapi_Attr attr = {0};
- slapi_attr_init(&attr, a->ai_type);
- rc = slapi_attr_is_dn_syntax_attr(&attr);
- attr_done(&attr);
- if (0 == rc) {
- return 0;
+
+ /*
+ * Treat cn and ou specially. Bring up the import workers for
+ * cn and ou even though they are not DN syntax attribute.
+ * This is done because they have some exceptional case to store
+ * DN format in the admin entries such as UserPreferences.
+ */
+ if ((0 == PL_strcasecmp("cn", a->ai_type)) ||
+ (0 == PL_strcasecmp("commonname", a->ai_type)) ||
+ (0 == PL_strcasecmp("ou", a->ai_type)) ||
+ (0 == PL_strcasecmp("organizationalUnit", a->ai_type))) {
+ ;
+ } else {
+ slapi_attr_init(&attr, a->ai_type);
+ rc = slapi_attr_is_dn_syntax_attr(&attr);
+ attr_done(&attr);
+ if (0 == rc) {
+ return 0;
+ }
}
}
diff --git a/ldap/servers/slapd/back-ldbm/import.h b/ldap/servers/slapd/back-ldbm/import.h
index e5569d34..e9843400 100644
--- a/ldap/servers/slapd/back-ldbm/import.h
+++ b/ldap/servers/slapd/back-ldbm/import.h
@@ -52,6 +52,7 @@
#define IMPORT_ADD_OP_ATTRS_OK 0
#define IMPORT_ADD_OP_ATTRS_NO_PARENT 1
+#define IMPORT_ADD_OP_ATTRS_SAVE_OLD_PID 2
#define IMPORT_COMPLETE_PASS 1
#define IMPORT_INCOMPLETE_PASS 2
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
index 0cb90623..4dabd81f 100644
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
@@ -195,6 +195,7 @@ int add_op_attrs(Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *ep,
backend *be;
char *pdn;
ID pid = 0;
+ int save_old_pid = 0;
slapi_pblock_get(pb, SLAPI_BACKEND, &be);
@@ -203,6 +204,9 @@ int add_op_attrs(Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *ep,
*/
if (NULL != status) {
+ if (IMPORT_ADD_OP_ATTRS_SAVE_OLD_PID == *status) {
+ save_old_pid = 1;
+ }
*status = IMPORT_ADD_OP_ATTRS_OK;
}
@@ -248,6 +252,16 @@ int add_op_attrs(Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *ep,
/* Get rid of attributes you're not allowed to specify yourself */
slapi_entry_delete_values( ep->ep_entry, hassubordinates, NULL );
slapi_entry_delete_values( ep->ep_entry, numsubordinates, NULL );
+
+ /* Upgrade DN format only */
+ /* Set current parentid to e_aux_attrs to remove it from the index file. */
+ if (save_old_pid) {
+ Slapi_Attr *pid_attr = NULL;
+ pid_attr = attrlist_remove(&ep->ep_entry->e_attrs, "parentid");
+ if (pid_attr) {
+ attrlist_add(&ep->ep_entry->e_aux_attrs, pid_attr);
+ }
+ }
/* Add the entryid, parentid and entrydn operational attributes */
/* Note: This function is provided by the Add code */
@@ -1376,11 +1390,12 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
run_from_cmdline = (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE);
slapi_pblock_get(pb, SLAPI_BACKEND_TASK, &task);
+ dblayer_txn_init(li, &txn);
+
if (run_from_cmdline) {
/* No ldbm backend exists until we process the config info. */
li->li_flags |= SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
ldbm_config_load_dse_info(li);
- txn.back_txn_txn = NULL; /* no transaction */
}
inst = ldbm_instance_find_by_name(li, instance_name);
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c
index 108c1655..e1891de6 100644
--- a/ldap/servers/slapd/dn.c
+++ b/ldap/servers/slapd/dn.c
@@ -493,13 +493,19 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len)
char *d = NULL; /* work pointer for dest */
char *ends = NULL;
char *endd = NULL;
- char *typestart = NULL;
- char *subtypestart = NULL; /* used for the nested DN */
char *lastesc = NULL;
+ /* rdn avs for the main DN */
+ char *typestart = NULL;
int rdn_av_count = 0;
struct berval *rdn_avs = NULL;
struct berval initial_rdn_av_stack[ SLAPI_DNNORM_INITIAL_RDN_AVS ];
+ /* rdn avs for the nested DN */
+ char *subtypestart = NULL; /* used for nested rdn avs */
+ int subrdn_av_count = 0;
+ struct berval *subrdn_avs = NULL;
+ struct berval subinitial_rdn_av_stack[ SLAPI_DNNORM_INITIAL_RDN_AVS ];
int chkblank = 0;
+ int avstat = 0;
if (NULL == dest) {
goto bail;
@@ -649,16 +655,18 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len)
* multivalued RDNs.
*/
if (subtypestart &&
- (ISPLUS(*(s+1)) || rdn_av_count > 0)) {
- add_rdn_av(subtypestart, d, &rdn_av_count,
- &rdn_avs, initial_rdn_av_stack);
+ (ISPLUS(*(s+1)) || subrdn_av_count > 0)) {
+ add_rdn_av(subtypestart, d, &subrdn_av_count,
+ &subrdn_avs, subinitial_rdn_av_stack);
}
if (!ISPLUS(*(s+1))) { /* at end of this RDN */
- if (rdn_av_count > 1) {
- sort_rdn_avs( rdn_avs, rdn_av_count, 1 );
+ if (subrdn_av_count > 1) {
+ sort_rdn_avs( subrdn_avs,
+ subrdn_av_count, 1 );
}
if (rdn_av_count > 0) {
- reset_rdn_avs( &rdn_avs, &rdn_av_count );
+ reset_rdn_avs( &subrdn_avs,
+ &subrdn_av_count );
subtypestart = NULL;
}
}
@@ -681,7 +689,7 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len)
}
} else if (((state == INVALUE1ST) &&
(s+2 < ends) && LEADNEEDSESCAPESTR(s+1)) ||
- ((state == INVALUE) &&
+ ((state == INVALUE) &&
(((s+2 < ends) && NEEDSESCAPESTR(s+1)) ||
(ISEOV(s+3, ends) && ISBLANKSTR(s+1))))) {
/* e.g., cn=abc\20 ,... */
@@ -724,16 +732,16 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len)
* multivalued RDNs.
*/
if (subtypestart &&
- (ISPLUSSTR(s+1) || rdn_av_count > 0)) {
- add_rdn_av(subtypestart, d, &rdn_av_count,
- &rdn_avs, initial_rdn_av_stack);
+ (ISPLUSSTR(s+1) || subrdn_av_count > 0)) {
+ add_rdn_av(subtypestart, d, &subrdn_av_count,
+ &subrdn_avs, subinitial_rdn_av_stack);
}
if (!ISPLUSSTR(s+1)) { /* at end of this RDN */
- if (rdn_av_count > 1) {
- sort_rdn_avs( rdn_avs, rdn_av_count, 1 );
+ if (subrdn_av_count > 1) {
+ sort_rdn_avs( subrdn_avs, subrdn_av_count, 1 );
}
- if (rdn_av_count > 0) {
- reset_rdn_avs( &rdn_avs, &rdn_av_count );
+ if (subrdn_av_count > 0) {
+ reset_rdn_avs( &subrdn_avs, &subrdn_av_count );
}
}
}
@@ -856,15 +864,15 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len)
* multivalued RDNs.
*/
if (ISPLUS(*s) || rdn_av_count > 0) {
- add_rdn_av(subtypestart, d, &rdn_av_count,
- &rdn_avs, initial_rdn_av_stack);
+ add_rdn_av(subtypestart, d, &subrdn_av_count,
+ &subrdn_avs, subinitial_rdn_av_stack);
}
if (!ISPLUS(*s)) { /* at end of this RDN */
- if (rdn_av_count > 1) {
- sort_rdn_avs( rdn_avs, rdn_av_count, 1 );
+ if (subrdn_av_count > 1) {
+ sort_rdn_avs( subrdn_avs, subrdn_av_count, 1 );
}
if (rdn_av_count > 0) {
- reset_rdn_avs( &rdn_avs, &rdn_av_count );
+ reset_rdn_avs( &subrdn_avs, &subrdn_av_count );
subtypestart = NULL;
}
}
@@ -1175,6 +1183,17 @@ slapi_dn_normalize( char *dn )
/* Introduced for the upgrade tool. DON'T USE THIS API! */
char *
+slapi_dn_normalize_original( char *dn )
+{
+ /* LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_dn_normalize \"%s\"\n", dn, 0, 0 ); */
+ *(substr_dn_normalize_orig( dn, dn + strlen( dn ))) = '\0';
+ /* LDAPDebug( LDAP_DEBUG_TRACE, "<= slapi_dn_normalize \"%s\"\n", dn, 0, 0 ); */
+
+ return( dn );
+}
+
+/* Introduced for the upgrade tool. DON'T USE THIS API! */
+char *
slapi_dn_normalize_case_original( char *dn )
{
/* LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_dn_normalize \"%s\"\n", dn, 0, 0 ); */
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 17f41990..f2bd3061 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -279,14 +279,19 @@ str2entry_fast( char *s, int flags, int read_stateinfo )
if (freetype) slapi_ch_free_string(&type);
continue;
}
- normdn = slapi_create_dn_string("%s", valuecharptr);
- if (NULL == normdn) {
- LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+ if (flags & SLAPI_STR2ENTRY_USE_OBSOLETE_DNFORMAT) {
+ normdn = slapi_ch_strdup(
+ slapi_dn_normalize_original(valuecharptr));
+ } else {
+ normdn = slapi_create_dn_string("%s", valuecharptr);
+ if (NULL == normdn) {
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"str2entry_fast: Invalid DN: %s\n", valuecharptr);
- slapi_entry_free( e );
- if (retmalloc) slapi_ch_free_string(&valuecharptr);
- if (freetype) slapi_ch_free_string(&type);
- return NULL;
+ slapi_entry_free( e );
+ if (retmalloc) slapi_ch_free_string(&valuecharptr);
+ if (freetype) slapi_ch_free_string(&type);
+ return NULL;
+ }
}
/* normdn is consumed in e */
slapi_entry_set_dn(e, normdn);
@@ -375,21 +380,26 @@ str2entry_fast( char *s, int flags, int read_stateinfo )
return NULL;
}
}
- rc = slapi_dn_normalize_ext(valuecharptr, 0, &dn_aval, &dnlen);
- if (rc < 0) {
- /* Give up normalizing the attribute value */
- LDAPDebug2Args(LDAP_DEBUG_TRACE,
+ if (flags & SLAPI_STR2ENTRY_USE_OBSOLETE_DNFORMAT) {
+ dn_aval = slapi_dn_normalize_original(valuecharptr);
+ slapi_value_set(value, dn_aval, strlen(dn_aval));
+ } else {
+ rc =
+ slapi_dn_normalize_ext(valuecharptr, 0, &dn_aval, &dnlen);
+ if (rc < 0) {
+ /* Give up normalizing the attribute value */
+ LDAPDebug2Args(LDAP_DEBUG_TRACE,
"str2entry_fast: Invalid DN value: %s: %s\n",
type, valuecharptr);
- dn_aval = valuecharptr;
- dnlen = valuelen;
- }
- slapi_value_set(value, dn_aval, dnlen);
- if (rc > 0) { /* if rc == 0, valuecharptr is passed in */
- slapi_ch_free_string(&dn_aval);
- } else if (rc == 0) { /* rc == 0; valuecharptr is passed in;
- not null terminated */
- *(dn_aval + dnlen) = '\0';
+ dn_aval = valuecharptr;
+ dnlen = valuelen;
+ }
+ slapi_value_set(value, dn_aval, dnlen);
+ if (rc > 0) {
+ /* rc > 0;
+ dn_aval was allocated in slapi_dn_normalize_ext */
+ slapi_ch_free_string(&dn_aval);
+ }
}
} else {
slapi_value_set(value, valuecharptr, valuelen);
@@ -1172,6 +1182,7 @@ free_and_return:
( SLAPI_STR2ENTRY_IGNORE_STATE \
| SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES \
| SLAPI_STR2ENTRY_TOMBSTONE_CHECK \
+ | SLAPI_STR2ENTRY_USE_OBSOLETE_DNFORMAT \
)
#define SLAPI_STRENTRY_FLAGS_HANDLED_BY_STR2ENTRY_FAST \
@@ -1197,7 +1208,7 @@ slapi_str2entry( char *s, int flags )
* slower but more forgiving str2entry_dupcheck() function.
*/
if ( 0 != ( flags & SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF ) ||
- 0 != ( flags & ~SLAPI_STRENTRY_FLAGS_HANDLED_BY_STR2ENTRY_FAST ))
+ 0 != ( flags & ~SLAPI_STRENTRY_FLAGS_HANDLED_BY_STR2ENTRY_FAST ))
{
e= str2entry_dupcheck( s, flags, read_stateinfo );
}
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 10da992f..534b6eb5 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -615,6 +615,7 @@ struct slapi_entry {
PRRWLock *e_virtual_lock; /* for access to cached vattrs */
void *e_extension; /* A list of entry object extensions */
unsigned char e_flags;
+ Slapi_Attr *e_aux_attrs; /* Attr list used for upgrade */
};
/*
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 045f1648..ff141084 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -882,6 +882,15 @@ Slapi_Entry *slapi_str2entry( char *s, int flags );
#define SLAPI_STR2ENTRY_NO_SCHEMA_LOCK 256
/**
+ * Normalize DN using obsolete DN normalizer.
+ *
+ * This marco is used only for the upgrading dn format tool.
+ *
+ * \see slapi_str2entry()
+ */
+#define SLAPI_STR2ENTRY_USE_OBSOLETE_DNFORMAT 512
+
+/**
* Generates a description of an entry as an LDIF string.
*
* This function behaves much like slapi_entry2str(); however, you can specify
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 7c8d9647..485e2940 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -375,6 +375,7 @@ Slapi_DN *slapi_sdn_init_dn_passin(Slapi_DN *sdn,const char *dn);
Slapi_DN *slapi_sdn_init_ndn_byref(Slapi_DN *sdn,const char *dn);
Slapi_DN *slapi_sdn_init_ndn_byval(Slapi_DN *sdn,const char *dn);
Slapi_DN *slapi_sdn_init_dn_ndn_byref(Slapi_DN *sdn,const char *dn);
+char * slapi_dn_normalize_original( char *dn );
char * slapi_dn_normalize_case_original( char *dn );
/* filter.c */