From 6f8fde543a757e59c03a09c45b0204aa0df97783 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Fri, 23 Nov 2012 11:15:52 +0100
Subject: [PATCH] Ticket 518 - dse.ldif is 0 length after server kill or
machine kill
Bug Description: If a machine is powered off while slapd is running, dse.ldif can have 0 bytes and
server doesn't start even if a dse.ldif.tmp or dse.ldif.bak exists
Fix Description: I see no way to prevent a 0 byte ldif in case of a machine crash from slapd code,
but the server should try all avaialble backup dse.ldif files to be able to start,
https://fedorahosted.org/389/ticket/518
Reviewed by: RichM (Thanks)
(cherry picked from commit b3ca9eec5d50c2ca503582e55b6681b9b3ad6ad3)
---
ldap/servers/slapd/config.c | 32 ++++----------------
ldap/servers/slapd/dse.c | 60 +++++++++++++++++++++++++-------------
ldap/servers/slapd/proto-slap.h | 1 +
3 files changed, 47 insertions(+), 46 deletions(-)
diff --git a/ldap/servers/slapd/config.c b/ldap/servers/slapd/config.c
index d97a575..3edc24b 100644
--- a/ldap/servers/slapd/config.c
+++ b/ldap/servers/slapd/config.c
@@ -165,6 +165,7 @@ slapd_bootstrap_config(const char *configdir)
char *buf = 0;
char *lastp = 0;
char *entrystr = 0;
+ char tmpfile[MAXPATHLEN+1];
if (NULL == configdir) {
slapi_log_error(SLAPI_LOG_FATAL,
@@ -173,33 +174,14 @@ slapd_bootstrap_config(const char *configdir)
}
PR_snprintf(configfile, sizeof(configfile), "%s/%s", configdir,
CONFIG_FILENAME);
- if ( (rc = PR_GetFileInfo( configfile, &prfinfo )) != PR_SUCCESS )
- {
- /* the "real" file does not exist; see if there is a tmpfile */
- char tmpfile[MAXPATHLEN+1];
- slapi_log_error(SLAPI_LOG_FATAL, "config",
- "The configuration file %s does not exist\n", configfile);
- PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.tmp", configdir,
+ PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.tmp", configdir,
CONFIG_FILENAME);
- if ( PR_GetFileInfo( tmpfile, &prfinfo ) == PR_SUCCESS ) {
- rc = PR_Rename(tmpfile, configfile);
- if (rc == PR_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, "config",
- "The configuration file %s was restored from backup %s\n",
- configfile, tmpfile);
- } else {
- slapi_log_error(SLAPI_LOG_FATAL, "config",
- "The configuration file %s was not restored from backup %s, error %d\n",
- configfile, tmpfile, rc);
- return rc; /* Fail */
- }
- } else {
- slapi_log_error(SLAPI_LOG_FATAL, "config",
- "The backup configuration file %s does not exist, either.\n",
- tmpfile);
- return rc; /* Fail */
- }
+ if ( (rc = dse_check_file(configfile, tmpfile)) == 0 ) {
+ PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.bak", configdir,
+ CONFIG_FILENAME);
+ rc = dse_check_file(configfile, tmpfile);
}
+
if ( (rc = PR_GetFileInfo( configfile, &prfinfo )) != PR_SUCCESS )
{
PRErrorCode prerr = PR_GetError();
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
index 8cf3916..efa64ff 100644
--- a/ldap/servers/slapd/dse.c
+++ b/ldap/servers/slapd/dse.c
@@ -651,6 +651,40 @@ dse_updateNumSubOfParent(struct dse *pdse, const Slapi_DN *child, int op)
slapi_sdn_done(&parent);
}
+/* check if a file is valid, or if a provided backup file can be used.
+ * there is no way to determine if the file contents is usable, the only
+ * checks that can be done is that the file exists and that it is not size 0
+ */
+int
+dse_check_file(char *filename, char *backupname)
+{
+ int rc= 0; /* Fail */
+ PRFileInfo prfinfo;
+
+ if (PR_GetFileInfo( filename, &prfinfo ) == PR_SUCCESS) {
+ if ( prfinfo.size > 0)
+ return (1);
+ else {
+ rc = PR_Delete (filename);
+ }
+ }
+
+ if (backupname)
+ rc = PR_Rename (backupname, filename);
+ else
+ return (0);
+
+ if ( PR_GetFileInfo( filename, &prfinfo ) == PR_SUCCESS && prfinfo.size > 0 ) {
+ slapi_log_error(SLAPI_LOG_FATAL, "dse",
+ "The configuration file %s was restored from backup %s\n", filename, backupname);
+ return (1);
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, "dse",
+ "The configuration file %s was not restored from backup %s, error %d\n",
+ filename, backupname, rc);
+ return (0);
+ }
+}
static int
dse_read_one_file(struct dse *pdse, const char *filename, Slapi_PBlock *pb,
int primary_file )
@@ -669,27 +703,11 @@ dse_read_one_file(struct dse *pdse, const char *filename, Slapi_PBlock *pb,
if ( (NULL != pdse) && (NULL != filename) )
{
- if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS )
- {
- /* the "real" file does not exist; see if there is a tmpfile */
- if ( pdse->dse_tmpfile &&
- PR_GetFileInfo( pdse->dse_tmpfile, &prfinfo ) == PR_SUCCESS ) {
- rc = PR_Rename(pdse->dse_tmpfile, filename);
- if (rc == PR_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, "dse",
- "The configuration file %s was restored from backup %s\n",
- filename, pdse->dse_tmpfile);
- rc = 1;
- } else {
- slapi_log_error(SLAPI_LOG_FATAL, "dse",
- "The configuration file %s was not restored from backup %s, error %d\n",
- filename, pdse->dse_tmpfile, rc);
- rc = 0;
- }
- } else {
- rc = 0; /* fail */
- }
- }
+ /* check if the "real" file exists and cam be used, if not try tmp as backup */
+ rc = dse_check_file(filename, pdse->dse_tmpfile);
+ if (!rc)
+ rc = dse_check_file(filename, pdse->dse_fileback);
+
if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS )
{
slapi_log_error(SLAPI_LOG_FATAL, "dse",
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 2289efa..bdcef9a 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -654,6 +654,7 @@ struct dse *dse_new( char *filename, char *tmpfilename, char *backfilename, char
struct dse *dse_new_with_filelist(char *filename, char *tmpfilename, char *backfilename, char *startokfilename, const char *configdir, char **filelist);
int dse_deletedse(Slapi_PBlock *pb);
int dse_destroy(struct dse *pdse);
+int dse_check_file(char *filename, char *backupname);
int dse_read_file(struct dse *pdse, Slapi_PBlock *pb);
int dse_bind( Slapi_PBlock *pb );
int dse_unbind( Slapi_PBlock *pb );
--
1.7.7.6