From f734217280efe98528d4be1544972cae1c12c8d6 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Fri, 16 May 2014 10:05:43 -0700 Subject: [PATCH 213/225] Ticket #47804 - db2bak.pl error with changelogdb Bug description: Backup utility db2bak[.pl] copies not just backend db files but also changelog db files, which is not associated with the backend instance, but the backend code blindly expected it. Fix description: If the copying directory is a changelog db dir, skip retrieving the backend instance info and just copy the files underneath https://fedorahosted.org/389/ticket/47804 Reviewed by rmeggins@redhat.com (Thank you, Rich!!) (cherry picked from commit a6c24c5bf1216e6dceaf014a25ce60a5a714635c) --- ldap/servers/slapd/back-ldbm/dbhelp.c | 6 +++ ldap/servers/slapd/back-ldbm/dblayer.c | 60 +++++++++++++------------- ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 4 +- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/ldap/servers/slapd/back-ldbm/dbhelp.c b/ldap/servers/slapd/back-ldbm/dbhelp.c index b0d17d3..797e2ae 100644 --- a/ldap/servers/slapd/back-ldbm/dbhelp.c +++ b/ldap/servers/slapd/back-ldbm/dbhelp.c @@ -139,6 +139,12 @@ dblayer_copy_file_keybykey(DB_ENV *env, (*(p + sizeof(LDBM_ENTRYRDN_STR) - 1) == '.')) { /* entryrdn.db */ struct attrinfo *ai = NULL; + if (NULL == inst) { + LDAPDebug0Args(LDAP_DEBUG_ANY, + "dblayer_copy_file_keybykey(entryrdn), " + "dup_cmp_fn cannot be retrieved since inst is NULL.\n"); + goto error; + } ainfo_get(inst->inst_be, LDBM_ENTRYRDN_STR, &ai); if (ai->ai_dup_cmp_fn) { /* If set, use the special dup compare callback */ diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c index 5fdca28..6f66a75 100644 --- a/ldap/servers/slapd/back-ldbm/dblayer.c +++ b/ldap/servers/slapd/back-ldbm/dblayer.c @@ -5526,17 +5526,15 @@ dblayer_copy_directory(struct ldbminfo *li, char *dest_dir, int restore, int *cnt, - int instance_dir_flag, int indexonly, - int resetlsns) + int resetlsns, + int is_changelog) { dblayer_private *priv = NULL; char *new_src_dir = NULL; char *new_dest_dir = NULL; PRDir *dirhandle = NULL; PRDirEntry *direntry = NULL; - size_t filename_length = 0; - size_t offset = 0; char *compare_piece = NULL; char *filename1; char *filename2; @@ -5545,8 +5543,8 @@ dblayer_copy_directory(struct ldbminfo *li, char *inst_dirp = NULL; char inst_dir[MAXPATHLEN]; char sep; - int suffix_len = 0; - ldbm_instance *inst = NULL; + int src_is_fullpath = 0; + ldbm_instance *inst = NULL; if (!src_dir || '\0' == *src_dir) { @@ -5570,20 +5568,28 @@ dblayer_copy_directory(struct ldbminfo *li, else relative_instance_name++; - inst = ldbm_instance_find_by_name(li, relative_instance_name); - if (NULL == inst) { - LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist; " - "Instance path %s could be invalid.\n", - relative_instance_name, src_dir, 0); - return return_value; + if (is_fullpath(src_dir)) { + src_is_fullpath = 1; + } + if (is_changelog) { + if (!src_is_fullpath) { + LDAPDebug1Arg(LDAP_DEBUG_ANY, "Changelogdir \"%s\" is not full path; " + "Skipping it.\n", src_dir); + return 0; + } + } else { + inst = ldbm_instance_find_by_name(li, relative_instance_name); + if (NULL == inst) { + LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist; " + "Instance path %s could be invalid.\n", + relative_instance_name, src_dir, 0); + return return_value; + } } - if (is_fullpath(src_dir)) - { + if (src_is_fullpath) { new_src_dir = src_dir; - } - else - { + } else { int len; inst_dirp = dblayer_get_full_inst_dir(inst->inst_li, inst, @@ -5610,7 +5616,6 @@ dblayer_copy_directory(struct ldbminfo *li, return return_value; } - suffix_len = sizeof(LDBM_SUFFIX) - 1; while (NULL != (direntry = PR_ReadDir(dirhandle, PR_SKIP_DOT | PR_SKIP_DOT_DOT))) { @@ -5624,15 +5629,10 @@ dblayer_copy_directory(struct ldbminfo *li, continue; } - /* Look at the last three characters in the filename */ - filename_length = strlen(direntry->name); - if (filename_length > suffix_len) { - offset = filename_length - suffix_len; - } else { - offset = 0; + compare_piece = PL_strrchr((char *)direntry->name, '.'); + if (NULL == compare_piece) { + compare_piece = (char *)direntry->name; } - compare_piece = (char *)direntry->name + offset; - /* rename .db3 -> .db4 or .db4 -> .db */ if (0 == strcmp(compare_piece, LDBM_FILENAME_SUFFIX) || 0 == strcmp(compare_piece, LDBM_SUFFIX_OLD) || @@ -5732,6 +5732,7 @@ out: /* * Get changelogdir from cn=changelog5,cn=config * The value does not have trailing spaces nor slashes. + * The changelogdir value must be a fullpath. */ static int _dblayer_get_changelogdir(struct ldbminfo *li, char **changelogdir) @@ -5947,7 +5948,7 @@ dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) return_value = dblayer_copy_directory(li, task, changelogdir, changelog_destdir, 0 /* backup */, - &cnt, 0, 0, 0); + &cnt, 0, 0, 1); if (return_value) { LDAPDebug(LDAP_DEBUG_ANY, "Backup: error in copying directory " @@ -6619,7 +6620,8 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * /* Get the parent dir of changelogdir */ *cldirname = '\0'; return_value = dblayer_copy_directory(li, task, filename1, - changelogdir, 1 /* restore */, &cnt, 0, 0, 0); + changelogdir, 1 /* restore */, + &cnt, 0, 0, 1); *cldirname = '/'; if (return_value) { LDAPDebug1Arg(LDAP_DEBUG_ANY, @@ -6651,7 +6653,7 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * restore_dir = inst->inst_parent_dir_name; /* If we're doing a partial restore, we need to reset the LSNs on the data files */ if (dblayer_copy_directory(li, task, filename1, - restore_dir, 1 /* restore */, &cnt, 0, 0, (bename) ? 1 : 0) == 0) + restore_dir, 1 /* restore */, &cnt, 0, (bename) ? 1 : 0, 0) == 0) continue; else { diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h index 499c92b..65cafea 100644 --- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -137,8 +137,8 @@ int dblayer_backup(struct ldbminfo *li, char *destination_directory, int dblayer_restore(struct ldbminfo *li, char* source_directory, Slapi_Task *task, char *bename); int dblayer_copy_directory(struct ldbminfo *li, Slapi_Task *task, char *instance_dir, char *destination_dir, - int restore, int *cnt, int instance_dir_flag, - int indexonly, int resetlsns); + int restore, int *cnt, int indexonly, + int resetlsns, int is_changelog); int dblayer_copyfile(char* source, char * destination, int overwrite, int mode); int dblayer_delete_instance_dir(backend *be); int dblayer_delete_database(struct ldbminfo *li); -- 1.8.1.4