From b2093e3016027d6b5cf06b3f91f30769bfc099e2 Mon Sep 17 00:00:00 2001 From: cvsadm Date: Fri, 21 Jan 2005 00:44:34 +0000 Subject: Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth) --- ldap/servers/slapd/protect_db.c | 758 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 758 insertions(+) create mode 100644 ldap/servers/slapd/protect_db.c (limited to 'ldap/servers/slapd/protect_db.c') diff --git a/ldap/servers/slapd/protect_db.c b/ldap/servers/slapd/protect_db.c new file mode 100644 index 00000000..34a63e80 --- /dev/null +++ b/ldap/servers/slapd/protect_db.c @@ -0,0 +1,758 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* protect_db.c + * Used to police access to the db. Prevents different instances of + * slapd from clobbering each other + */ + + + +#ifndef _WIN32 + +#define LOCK_DIR "locks" +#define LOCK_FILE "lock" +#define IMPORT_DIR "imports" +#define EXPORT_DIR "exports" +#define SERVER_DIR "server" +#define NUM_TRIES 20 +#define WAIT_TIME 250 + +#include +#include +#include +#include /* open */ +#include +#include +#include +#include /* MAXPATHLEN */ +#include +#include +#endif + +#include "protect_db.h" + +#include "slap.h" + + +#ifndef _WIN32 +/* This is the unix version of the code to protect the db. */ + +static int +grab_lockfile() +{ + pid_t pid, owning_pid; + char lockfile[MAXPATHLEN]; + int fd, x; + int removed_lockfile = 0; + struct timeval t; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + + /* Don't use anything that makes a NSPR call here (like LDAPDebug)! This function + gets called by an atexit function, and NSPR is long gone by then. */ + + /* Get the name of the lockfile */ + sprintf(lockfile, "%s/%s", slapdFrontendConfig->instancedir, LOCK_FILE); + /* Get our pid */ + pid = getpid(); + + /* Try to grab it */ + if ((fd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, 0664)) != -1) { + /* We got the lock, write our pid to the file */ + write(fd, (void *) &pid, sizeof(pid_t)); + close(fd); + return 0; + } + + /* We weren't able to get the lock. Find out why. */ + if (errno != EEXIST) { + /* Hmm, something happened that we weren't prepared to handle */ + fprintf(stderr, ERROR_ACCESSING_LOCKFILE, lockfile); + return -1; + } + + while(1) { + /* Try to grab the lockfile NUM_TRIES times waiting WAIT_TIME milliseconds after each try */ + t.tv_sec = 0; + t.tv_usec = WAIT_TIME * 1000; + for(x = 0; x < NUM_TRIES; x++) { + if ((fd = open(lockfile, O_RDWR | O_CREAT | O_EXCL)) != -1) { + /* Got the lock */ + write(fd, (void *) &pid, sizeof(pid_t)); + close(fd); + return 0; + } + select(0, NULL, NULL, NULL, &t); + } + + /* We still haven't got the lockfile. Find out who owns it and see if they are still up */ + if ((fd = open(lockfile, O_RDONLY)) != -1) { + size_t nb_bytes=0; + + nb_bytes = read(fd, (void *) &owning_pid, sizeof(pid_t)); + if ( (nb_bytes != (size_t)(sizeof(pid_t)) ) || (owning_pid == 0) || (kill(owning_pid, 0) != 0 && errno == ESRCH) ) { + /* The process that owns the lock is dead. Try to remove the old lockfile. */ + if (unlink(lockfile) != 0) { + /* Unable to remove the stale lockfile. */ + fprintf(stderr, LOCKFILE_DEAD_OWNER, lockfile, owning_pid); + return -1; + } + if (removed_lockfile) { + /* We already removed the lockfile once. Best thing to do is give up. */ + /* I'm not sure what should be given as an error here */ + fprintf(stderr, UNABLE_TO_GET_LOCKFILE, lockfile); + return -1; + } else { + removed_lockfile = 1; + } + } else { + /* It looks like the owner of the lockfile is still up and running. */ + fprintf(stderr, LOCKFILE_ALREADY_OWNED, owning_pid); + return -1; + } + } + } +} + +static void +release_lockfile() +{ + char lockfile[MAXPATHLEN]; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + /* This function assumes that the caller owns the lock, it doesn't check to make sure! */ + + sprintf(lockfile, "%s/%s", slapdFrontendConfig->instancedir, LOCK_FILE); + unlink(lockfile); +} + + +/* Takes the pid of a process. Returns 1 if the process seems + * to be up, otherwise it returns 0. + */ +static int +is_process_up(pid_t pid) +{ + if (kill(pid, 0) == -1 && errno == ESRCH) { + return 0; + } else { + return 1; + } +} + +/* Make sure the directory 'dir' exists and is owned bye the user + * the server runs as. Returns 0 if everything is ok. + */ +static int +make_sure_dir_exists(char *dir) +{ + struct passwd* pw; + struct stat stat_buffer; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + /* Make sure it exists */ + if (PR_MkDir(dir, 0755) != PR_SUCCESS) { + PRErrorCode prerr = PR_GetError(); + if (prerr != PR_FILE_EXISTS_ERROR) { + LDAPDebug(LDAP_DEBUG_ANY, FILE_CREATE_ERROR, dir, prerr, slapd_pr_strerror(prerr)); + return 1; + } + } + + /* Make sure it's owned by the correct user */ + if (slapdFrontendConfig->localuser != NULL) { + if ( (pw = getpwnam(slapdFrontendConfig->localuser)) == NULL ) { + LDAPDebug(LDAP_DEBUG_ANY, GETPWNAM_WARNING, slapdFrontendConfig->localuser, errno, strerror(errno)); + } else { + if (chown(dir, pw->pw_uid, -1) == -1) { + stat(dir, &stat_buffer); + if (stat_buffer.st_uid != pw->pw_uid) { + LDAPDebug(LDAP_DEBUG_ANY, CHOWN_WARNING, dir, 0, 0); + } + } + } /* else */ + } + + return 0; +} + +/* Creates a file in the directory 'dir_name' whose name is the + * pid for this process. + */ +static void +add_this_process_to(char *dir_name) +{ + char file_name[MAXPATHLEN]; + struct passwd* pw; + struct stat stat_buffer; + PRFileDesc* prfd; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + sprintf(file_name, "%s/%d", dir_name, getpid()); + + if ((prfd = PR_Open(file_name, PR_RDWR | PR_CREATE_FILE, 0666)) == NULL) { + LDAPDebug(LDAP_DEBUG_ANY, FILE_CREATE_WARNING, file_name, 0, 0); + return; + } + + /* Make sure the owner is of the file is the user the server + * runs as. */ + if (slapdFrontendConfig->localuser != NULL) { + if ( (pw = getpwnam(slapdFrontendConfig->localuser)) == NULL ) { + LDAPDebug(LDAP_DEBUG_ANY, GETPWNAM_WARNING, slapdFrontendConfig->localuser, errno, strerror(errno)); + } else { + if (chown(file_name, pw->pw_uid, -1) == -1) { + stat(file_name, &stat_buffer); + if (stat_buffer.st_uid != pw->pw_uid) { + LDAPDebug(LDAP_DEBUG_ANY, CHOWN_WARNING, file_name, 0, 0); + } + } + } /* else */ + } + PR_Close(prfd); +} + + +/* The directory 'dir_name' is expected to contain files whose + * names are the pid of running slapd processes. This + * function will check each entry in the directory and remove + * any files that represent processes that don't exist. + * Returns 0 if there are no processes represented, or + * the pid of one of the processes. + */ +static long +sample_and_update(char *dir_name) +{ + PRDir *dir; + PRDirEntry *entry; + pid_t pid; + long result = 0; + char *endp; + char file_name[MAXPATHLEN]; + + if ((dir = PR_OpenDir(dir_name)) == NULL) { + return 0; + } + + while((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) { + pid = (pid_t) strtol(entry->name, &endp, 0); + if (*endp != '\0') { + /* not quite sure what this file was, but we + * didn't put it there */ + continue; + } + if (is_process_up(pid)) { + result = (long) pid; + } else { + sprintf(file_name, "%s/%s", dir_name, entry->name); + PR_Delete(file_name); + } + } + PR_CloseDir(dir); + return result; +} + + +/* Removes any stale pid entries and the pid entry for this + * process from the directory 'dir_name'. + */ +static void +remove_and_update(char *dir_name) +{ + /* since this is called from an atexit function, we can't use + * NSPR. */ + + DIR *dir; + struct dirent *entry; + pid_t pid; + pid_t our_pid; + char *endp; + char file_name[MAXPATHLEN]; + + /* get our pid */ + our_pid = getpid(); + + if ((dir = opendir(dir_name)) == NULL) { + return; + } + + while((entry = readdir(dir)) != NULL) { + + /* skip dot and dot-dot */ + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) + continue; + + pid = (pid_t) strtol(entry->d_name, &endp, 0); + if (*endp != '\0') { + /* not quite sure what this file was, but we + * didn't put it there */ + continue; + } + if (!is_process_up(pid) || pid == our_pid) { + sprintf(file_name, "%s/%s", dir_name, entry->d_name); + unlink(file_name); + } + } + closedir(dir); +} + + + +/* Walks through all the pid directories and clears any stale + * pids. It also removes the files for this process. + */ +void +remove_slapd_process() +{ + char lock_dir[MAXPATHLEN]; + char import_dir[MAXPATHLEN]; + char export_dir[MAXPATHLEN]; + char server_dir[MAXPATHLEN]; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + + /* Create the name of the directories that hold the pids of the currently running + * ns-slapd processes */ + sprintf(lock_dir, "%s/%s", slapdFrontendConfig->instancedir, LOCK_DIR); + sprintf(import_dir, "%s/%s/%s", slapdFrontendConfig->instancedir, LOCK_DIR, IMPORT_DIR); + sprintf(export_dir, "%s/%s/%s", slapdFrontendConfig->instancedir, LOCK_DIR, EXPORT_DIR); + sprintf(server_dir, "%s/%s/%s", slapdFrontendConfig->instancedir, LOCK_DIR, SERVER_DIR); + + /* Grab the lockfile */ + if (grab_lockfile() != 0) { + /* Unable to grab the lockfile */ + return; + } + + + remove_and_update(import_dir); + remove_and_update(export_dir); + remove_and_update(server_dir); + + release_lockfile(); +} + +int +add_new_slapd_process(int exec_mode, int r_flag, int skip_flag) +{ + char lock_dir[MAXPATHLEN]; + char import_dir[MAXPATHLEN]; + char export_dir[MAXPATHLEN]; + char server_dir[MAXPATHLEN]; + int running, importing, exporting; + int result = 0; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + if (skip_flag) { + return 0; + } + + /* Create the name of the directories that hold the pids of the currently running + * ns-slapd processes */ + sprintf(lock_dir, "%s/%s", slapdFrontendConfig->instancedir, LOCK_DIR); + sprintf(import_dir, "%s/%s/%s", slapdFrontendConfig->instancedir, LOCK_DIR, IMPORT_DIR); + sprintf(export_dir, "%s/%s/%s", slapdFrontendConfig->instancedir, LOCK_DIR, EXPORT_DIR); + sprintf(server_dir, "%s/%s/%s", slapdFrontendConfig->instancedir, LOCK_DIR, SERVER_DIR); + + /* Grab the lockfile */ + if (grab_lockfile() != 0) { + /* Unable to grab the lockfile */ + return -1; + } + + /* Make sure the directories exist */ + if (make_sure_dir_exists(lock_dir) != 0 || + make_sure_dir_exists(import_dir) != 0 || + make_sure_dir_exists(export_dir) != 0 || + make_sure_dir_exists(server_dir) != 0) { + release_lockfile(); + return -1; + } + + /* Go through the directories and find out what's going on. + * Clear any stale pids encountered. */ + importing = sample_and_update(import_dir); + exporting = sample_and_update(export_dir); + running = sample_and_update(server_dir); + + switch (exec_mode) { + case SLAPD_EXEMODE_SLAPD: + if (running) { + result = -1; + LDAPDebug(LDAP_DEBUG_ANY, NO_SERVER_DUE_TO_SERVER, running, 0, 0); + } else if (importing) { + result = -1; + LDAPDebug(LDAP_DEBUG_ANY, NO_SERVER_DUE_TO_IMPORT, importing, 0, 0); + } else { + add_this_process_to(server_dir); + result = 0; + } + break; + case SLAPD_EXEMODE_DB2LDIF: + if (r_flag) { + /* When the -r flag is used in db2ldif we need to make sure + * we get a consistent snapshot of the server. As a result + * it needs to run by itself, so no other slapd process can + * change the database while it is running. */ + if (running || importing) { + LDAPDebug(LDAP_DEBUG_ANY, NO_DB2LDIFR_DUE_TO_USE, 0, 0, 0); + result = -1; + } else { + /* Even though this is really going to export code, we will + * but it in the importing dir so no other process can change + * things while we are doing ldif2db with the -r flag. */ + add_this_process_to(import_dir); + result = 0; + } + } else { + if (importing) { + LDAPDebug(LDAP_DEBUG_ANY, NO_DB2LDIF_DUE_TO_IMPORT, importing, 0, 0); + result = -1; + } else { + add_this_process_to(export_dir); + result = 0; + } + } + break; + case SLAPD_EXEMODE_DB2ARCHIVE: + if (importing) { + LDAPDebug(LDAP_DEBUG_ANY, NO_DB2BAK_DUE_TO_IMPORT, importing, 0, 0); + result = -1; + } else { + add_this_process_to(export_dir); + result = 0; + } + break; + case SLAPD_EXEMODE_ARCHIVE2DB: + case SLAPD_EXEMODE_LDIF2DB: + if (running || importing || exporting) { + LDAPDebug(LDAP_DEBUG_ANY, NO_IMPORT_DUE_TO_USE, 0, 0, 0); + result = -1; + } else { + add_this_process_to(import_dir); + result = 0; + } + break; + case SLAPD_EXEMODE_DB2INDEX: + if (running || importing || exporting) { + LDAPDebug(LDAP_DEBUG_ANY, NO_DB2INDEX_DUE_TO_USE, 0, 0, 0); + result = -1; + } else { + add_this_process_to(import_dir); + result = 0; + } + break; +#if defined(UPGRADEDB) + case SLAPD_EXEMODE_UPGRADEDB: + if (running || importing || exporting) { + LDAPDebug(LDAP_DEBUG_ANY, NO_UPGRADEDB_DUE_TO_USE, 0, 0, 0); + result = -1; + } else { + add_this_process_to(import_dir); + result = 0; + } + break; +#endif + case SLAPD_EXEMODE_DBTEST: + if (running || importing || exporting) { + LDAPDebug(LDAP_DEBUG_ANY, NO_DBTEST_DUE_TO_USE, 0, 0, 0); + result = -1; + } else { + add_this_process_to(import_dir); + result = 0; + } + break; + } + + release_lockfile(); + + if (result == 0) { + atexit(remove_slapd_process); + } + + return result; +} + + + +/* is_slapd_running() + * returns 1 if slapd is running, 0 if not, -1 on error + */ + + +int +is_slapd_running() { + char server_dir[MAXPATHLEN]; + char lock_dir[MAXPATHLEN]; + slapdFrontendConfig_t *cfg = getFrontendConfig(); + int running = 0; + + sprintf(lock_dir, "%s/%s", cfg->instancedir, LOCK_DIR); + sprintf( server_dir, "%s/%s/%s", cfg->instancedir, LOCK_DIR, SERVER_DIR); + + /* Grab the lockfile */ + if (grab_lockfile() != 0) { + /* Unable to grab the lockfile */ + return -1; + } + + /* Make sure the directories exist */ + if (make_sure_dir_exists(lock_dir) != 0 || + make_sure_dir_exists(server_dir) != 0) { + release_lockfile(); + return -1; + } + + running = sample_and_update(server_dir); + release_lockfile(); + return running; +} + + +#else /* _WIN32 */ + +/* The NT version of this code */ + +/* Returns 1 if the mutex named 'mutexName' otherwise it + * returns 0 + */ +int +mutex_exists( char *mutexName ) +{ + if ( OpenMutex( SYNCHRONIZE, FALSE, mutexName ) == NULL ) { + return( 0 ); + } else { + return( 1 ); + } +} + +/* is_slapd_running(): + * returns 1 if slapd is running, 0 if not + */ + +int +is_slapd_running() { + char mutexName[ MAXPATHLEN + 1 ]; + char serverMutexName[ MAXPATHLEN + 1 ]; + int result = 0; + slapdFrontendConfig_t *cfg = getFrontendConfig(); + + strncpy( mutexName, cfg->instancedir, MAXPATHLEN ); + strncpy( serverMutexName, cfg->instancedir, MAXPATHLEN ); + mutexName[ MAXPATHLEN ] = '\0'; + + serverMutexName[ MAXPATHLEN ] = '\0'; + strcat( serverMutexName, "/server" ); + + return mutex_exists ( serverMutexName ); +} + +static void fix_mutex_name(char *name) +{ + /* On NT mutex names cannot contain the '\' character. + * This functions replaces '\' with '/' in the supplied + * name. */ + int x; + + for (x = 0; name[x] != '\0'; x++) { + if ('\\' == name[x]) { + name[x] = '/'; + } + } +} + +/* + * We retain any opened handle to the mutex we create here, + * to use when we shutdown, to delete the mutex prior to + * signaling that we've exited. + */ +static HANDLE open_mutex = NULL; + +/* + * Call this to clean up the locks, before signaling + * that the server is down. + */ +void +remove_slapd_process() +{ + if (open_mutex) { + CloseHandle(open_mutex); + } +} + +/* This function makes sure different instances of slapd don't + * run in conflicting modes at the same time. The WIN32 version + * uses mutexes as names that the kernel handles. Basically there + * is a server mutex, and import mutex, and an export mutex. If + * the server mutex exists, then the server is running. If the + * import mutex exists, then either ldif2db or bak2db is running. + * If the export mutex exists, then one or more of db2ldif or db2bak + * are running. There is also a mutex that is actually locked when + * checking the existence of the other mutexes. The OS will + * automatically remove a mutex if no process has a handle on it. + * returns a 0 if it is ok for the process to run + * returns a -1 if the process can't run do to a conflict with other + * slapd processes + */ +int +add_new_slapd_process(int exec_mode, int r_flag, int skip_flag) +{ + char mutexName[ MAXPATHLEN + 1 ]; + char serverMutexName[ MAXPATHLEN + 1 ]; + char importMutexName[ MAXPATHLEN + 1 ]; + char exportMutexName[ MAXPATHLEN + 1 ]; + + HANDLE mutex; + SECURITY_ATTRIBUTES mutexAttributes; + PSECURITY_DESCRIPTOR pSD; + LPVOID lpMsgBuf; + + int result = 0; + + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + if (skip_flag) { + return 0; + } + + /* Create the names for the mutexes */ + strcpy(mutexName, slapdFrontendConfig->instancedir); + + /* Make sure the name of the mutex is legal. */ + fix_mutex_name(mutexName); + + sprintf(serverMutexName, "%s/server", mutexName); + sprintf(importMutexName, "%s/import", mutexName); + sprintf(exportMutexName, "%s/export", mutexName); + + /* Fill in the security crap for the mutex */ + pSD = (PSECURITY_DESCRIPTOR)slapi_ch_malloc( sizeof( SECURITY_DESCRIPTOR ) ); + InitializeSecurityDescriptor( pSD, SECURITY_DESCRIPTOR_REVISION ); + SetSecurityDescriptorDacl( pSD, TRUE, NULL, FALSE ); + mutexAttributes.nLength = sizeof( mutexAttributes ); + mutexAttributes.lpSecurityDescriptor = pSD; + mutexAttributes.bInheritHandle = FALSE; + + /* Get a handle to the main mutex */ + if ( ( mutex = CreateMutex( &mutexAttributes, FALSE, mutexName ) ) == NULL ) { + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + LDAPDebug( LDAP_DEBUG_ANY, CREATE_MUTEX_ERROR, lpMsgBuf, 0, 0 ); + LocalFree( lpMsgBuf ); + exit( 1 ); + } + + /* Lock the main mutex */ + if ( WaitForSingleObject( mutex, INFINITE ) == WAIT_FAILED ) { + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + LDAPDebug( LDAP_DEBUG_ANY, WAIT_ERROR, lpMsgBuf, 0, 0 ); + LocalFree( lpMsgBuf ); + exit( 1 ); + } + + + switch (exec_mode) { + case SLAPD_EXEMODE_SLAPD: + if ( mutex_exists( serverMutexName ) || + mutex_exists( importMutexName ) ) { + LDAPDebug( LDAP_DEBUG_ANY, NO_SERVER_DUE_TO_USE, 0, 0, 0); + result = -1; + } else { + open_mutex = CreateMutex( &mutexAttributes, FALSE, serverMutexName ); + result = 0; + } + break; + case SLAPD_EXEMODE_DB2LDIF: + if (r_flag) { + /* When the -r flag is used in db2ldif we need to make sure + * we get a consistent snapshot of the server. As a result + * it needs to run by itself, so no other slapd process can + * change the database while it is running. */ + if ( mutex_exists( serverMutexName ) || + mutex_exists( importMutexName ) || + mutex_exists( exportMutexName ) ) { + LDAPDebug(LDAP_DEBUG_ANY, NO_DB2LDIFR_DUE_TO_USE, 0, 0, 0); + result = -1; + } else { + CreateMutex( &mutexAttributes, FALSE, exportMutexName ); + result = 0; + } + break; + } + case SLAPD_EXEMODE_DB2ARCHIVE: + if ( mutex_exists( importMutexName ) ) { + LDAPDebug(LDAP_DEBUG_ANY, NO_EXPORT_DUE_TO_IMPORT, 0, 0, 0); + result = -1; + } else { + CreateMutex( &mutexAttributes, FALSE, exportMutexName ); + result = 0; + } + break; + case SLAPD_EXEMODE_ARCHIVE2DB: + case SLAPD_EXEMODE_LDIF2DB: + if ( mutex_exists( serverMutexName ) || + mutex_exists( importMutexName ) || + mutex_exists( exportMutexName ) ) { + LDAPDebug(LDAP_DEBUG_ANY, NO_IMPORT_DUE_TO_USE, 0, 0, 0); + result = -1; + } else { + CreateMutex( &mutexAttributes, FALSE, importMutexName ); + result = 0; + } + break; +#if defined(UPGRADEDB) + case SLAPD_EXEMODE_UPGRADEDB: + if ( mutex_exists( serverMutexName ) || + mutex_exists( importMutexName ) || + mutex_exists( exportMutexName ) ) { + LDAPDebug(LDAP_DEBUG_ANY, NO_UPGRADEDB_DUE_TO_USE, 0, 0, 0); + result = -1; + } else { + CreateMutex( &mutexAttributes, FALSE, importMutexName ); + result = 0; + } + break; +#endif + case SLAPD_EXEMODE_DBTEST: + if ( mutex_exists( serverMutexName ) || + mutex_exists( importMutexName ) || + mutex_exists( exportMutexName ) ) { + LDAPDebug(LDAP_DEBUG_ANY, NO_DBTEST_DUE_TO_USE, 0, 0, 0); + result = -1; + } else { + CreateMutex( &mutexAttributes, FALSE, importMutexName ); + result = 0; + } + break; + } + + /* release the main mutex */ + ReleaseMutex( mutex ); + + slapi_ch_free((void**)&pSD ); + + return( result ); +} +#endif /* _WIN32 */ + -- cgit