Author: rmeggins
Update of /cvs/dirsec/ldapserver/ldap/servers/plugins/replication
In directory
cvs-int.fedora.redhat.com:/tmp/cvs-serv3313/ldapserver/ldap/servers/plugins/replication
Modified Files:
cl5_api.c cl5_api.h cl5_config.c
Log Message:
Resolves: bug 185602
Bug Description: Netscape Console allows instance directory to be set as change log
Reviewed by: nkinder (Thanks!)
Fix Description: 1) When removing the changelog files and directories, only remove the
actual db related files - version, guardian, *db4, log.*, and __db.* - This should take
care of the cases where the changelog was already created in an existing directory.
2) Disallow adding/changing a changelog db directory if it already exists and is not
empty
Platforms tested: RHEL5 x86_64
Flag Day: no
Doc impact: no
QA impact: should be covered by regular nightly and manual testing
New Tests integrated into TET: none
Index: cl5_api.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/replication/cl5_api.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- cl5_api.c 12 Oct 2007 17:22:54 -0000 1.17
+++ cl5_api.c 16 Oct 2007 21:22:47 -0000 1.18
@@ -3835,6 +3835,39 @@
}
}
+/* see if the given file is a changelog db file */
+static int
+_cl5IsDbFile(const char *fname)
+{
+ char *ptr = NULL;
+ if (!fname || !*fname) {
+ return 0;
+ }
+
+ if (!strcmp(fname, GUARDIAN_FILE)) {
+ return 1;
+ }
+
+ if (!strcmp(fname, VERSION_FILE)) {
+ return 1;
+ }
+
+ if (_cl5FileEndsWith(fname, DB_EXTENSION)) {
+ return 1;
+ }
+
+ if (_cl5IsLogFile(fname)) {
+ return 1;
+ }
+
+ ptr = strstr(fname, "__db.");
+ if (ptr == fname) { /* begins with __db. */
+ return 1;
+ }
+
+ return 0; /* not a filename we recognize as being associated with the db */
+}
+
/* state lock must be locked */
static int _cl5Delete (const char *clDir, int rmDir)
{
@@ -3842,6 +3875,7 @@
char filename[MAXPATHLEN + 1];
PRDirEntry *entry = NULL;
int rc;
+ int dirisempty = 1;
/* remove all files in the directory and the directory */
dir = PR_OpenDir(clDir);
@@ -3860,6 +3894,13 @@
{
break;
}
+ if (!_cl5IsDbFile(entry->name)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl,
+ "_cl5Delete: Skipping file [%s/%s] because it is not a changelogdb
file.\n",
+ clDir, entry->name);
+ dirisempty = 0; /* skipped at least one file - dir not empty */
+ continue;
+ }
PR_snprintf(filename, MAXPATHLEN, "%s/%s", clDir, entry->name);
rc = PR_Delete(filename);
if (rc != PR_SUCCESS)
@@ -3879,7 +3920,7 @@
return CL5_SYSTEM_ERROR;
}
- if (rmDir)
+ if (rmDir && dirisempty)
{
rc = PR_RmDir (clDir);
if (rc != 0)
@@ -3889,6 +3930,10 @@
clDir, errno);
return CL5_SYSTEM_ERROR;
}
+ } else if (rmDir && !dirisempty) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl,
+ "_cl5Delete: changelog dir (%s) is not empty - cannot remove\n",
+ clDir);
}
return CL5_SUCCESS;
@@ -6770,3 +6815,35 @@
#endif
return rval;
}
+
+int
+cl5DbDirIsEmpty(const char *dir)
+{
+ PRDir *prDir;
+ PRDirEntry *prDirEntry;
+ int isempty = 1;
+
+ if (!dir || !*dir) {
+ return isempty;
+ }
+ /* assume failure means it does not exist - other failure
+ cases will be handled by code which attempts to create the
+ db in this directory */
+ if (PR_Access(dir, PR_ACCESS_EXISTS)) {
+ return isempty;
+ }
+ prDir = PR_OpenDir(dir);
+ if (prDir == NULL) {
+ return isempty; /* assume failure means does not exist */
+ }
+ while (NULL != (prDirEntry = PR_ReadDir(prDir, PR_SKIP_DOT | PR_SKIP_DOT_DOT))) {
+ if (NULL == prDirEntry->name) { /* NSPR doesn't behave like the docs say it
should */
+ break;
+ }
+ isempty = 0; /* found at least one "real" file */
+ break;
+ }
+ PR_CloseDir(prDir);
+
+ return isempty;
+}
Index: cl5_api.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/replication/cl5_api.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- cl5_api.h 15 Mar 2007 21:40:34 -0000 1.7
+++ cl5_api.h 16 Oct 2007 21:22:47 -0000 1.8
@@ -519,4 +519,13 @@
int cl5_is_diskfull();
int cl5_diskspace_is_available();
+/* Name: cl5DbDirIsEmpty
+ Description: See if the given cldb directory is empty or doesn't yet exist.
+ Parameters: dir - Contains the name of the directory.
+ Return: TRUE - directory does not exist or is empty, is NULL, or is
+ an empty string
+ FALSE - otherwise
+*/
+int cl5DbDirIsEmpty(const char *dir);
+
#endif
Index: cl5_config.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/replication/cl5_config.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- cl5_config.c 10 Nov 2006 23:45:17 -0000 1.6
+++ cl5_config.c 16 Oct 2007 21:22:47 -0000 1.7
@@ -205,6 +205,20 @@
goto done;
}
+ if (!cl5DbDirIsEmpty(config.dir))
+ {
+ *returncode = 1;
+ if (returntext)
+ {
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "The changelog directory [%s] already exists and is not empty. "
+ "Please choose a directory that does not exist or is empty.\n",
+ config.dir);
+ }
+
+ goto done;
+ }
+
/* start the changelog */
rc = cl5Open (config.dir, &config.dbconfig);
if (rc != CL5_SUCCESS)
@@ -450,6 +464,20 @@
if (strcmp (currentDir, config.dir) != 0)
#endif
{
+ if (!cl5DbDirIsEmpty(config.dir))
+ {
+ *returncode = 1;
+ if (returntext)
+ {
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "The changelog directory [%s] already exists and is not empty. "
+ "Please choose a directory that does not exist or is empty.\n",
+ config.dir);
+ }
+
+ goto done;
+ }
+
if (!_is_absolutepath(config.dir) || (CL5_SUCCESS !=
cl5CreateDirIfNeeded(config.dir)))
{
*returncode = 1;