From bd35ae5be634845b78da79583390caa72747b09c Mon Sep 17 00:00:00 2001 From: Nathan Kinder Date: Aug 31 2007 17:01:38 +0000 Subject: Resolves: 258341 Summary: Fix rundir and instancedir location functions in dsalib. --- diff --git a/admserv/cgi-ds/ds_remove.c b/admserv/cgi-ds/ds_remove.c deleted file mode 100644 index 54ff4b0..0000000 --- a/admserv/cgi-ds/ds_remove.c +++ /dev/null @@ -1,254 +0,0 @@ -/** BEGIN COPYRIGHT BLOCK - * This Program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; version 2 of the License. - * - * This Program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA. - * - * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. - * Copyright (C) 2005 Red Hat, Inc. - * All rights reserved. - * END COPYRIGHT BLOCK **/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -/* - * Remove the server - * - * Prasanta Behera - */ -#ifdef XP_WIN32 -#include -#include -#include "regparms.h" -extern BOOL DeleteServer(LPCSTR pszServiceId); -#endif - -#include -#include -#include -#include "libadminutil/admutil.h" -#ifdef XP_UNIX -#include -#include -#include -#include -#include -#include -#else -#endif /* WIN32? */ -#include - -#include "dsalib.h" -#include "init_ds_env.h" - - -#include "nspr.h" - -/* this will be set to 1 if we need to retry the - rm -rf of the instance directory again */ -static int try_rm_rf_again = 0; - -static int -rm_rf_err_func(const char *path, const char *op, void *arg) -{ - PRInt32 errcode = PR_GetError(); - char *msg; - const char *errtext; - - if (!errcode || (errcode == PR_UNKNOWN_ERROR)) { - errcode = PR_GetOSError(); - errtext = ds_system_errmsg(); - } else { - errtext = PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT); - } - - /* ignore "file or directory already removed" errors */ - if (errcode != PR_FILE_NOT_FOUND_ERROR) { - msg = PR_smprintf("%s %s: error code %d (%s)", op, path, errcode, errtext); - ds_send_error(msg, 0); - PR_smprintf_free(msg); - } - - /* On Windows and HPUX, if the file/directory to remove is opened by another - application, it cannot be removed and will generate a busy error - This usually happens when we attempt to stop slapd then remove the - instance directory, but for some reason the process still has some - open files - In this case, we need to wait for some period of time then attempt to - remove the instance directory again - */ - if (errcode == PR_FILE_IS_BUSY_ERROR) { - try_rm_rf_again = 1; - return 0; /* just abort the operation */ - } - -#ifdef XP_WIN32 - /* on windows, err 145 means dir not empty - 145 The directory is not empty. ERROR_DIR_NOT_EMPTY - If there was a busy file, it wasn't able to be - removed, so when we go to remove the directory, it - won't be empty - */ - if (errcode == ERROR_DIR_NOT_EMPTY) { - if (try_rm_rf_again) { - return 0; /* don't continue */ - } - } -#else /* unix */ - if (errcode == EEXIST) { /* not empty */ - if (try_rm_rf_again) { - return 0; /* don't continue */ - } - } -#endif - - return 1; /* just continue */ -} - -int main(int argc, char *argv[]) -{ - int status = -1; - char *servername; - char *instdir; - int isRunning; -#ifndef __LP64__ -#if defined(__hpux) && !defined(__ia64) - _main(); -#endif -#endif - -#ifdef XP_WIN32 - if ( getenv("DEBUG_DSINST") ) - DebugBreak(); -#endif - - /* case 1: being called as program -f inffile */ - if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'f') - { - FILE *infFile = fopen(argv[2], "r"); - if (!infFile) - { - ds_report_error (DS_INCORRECT_USAGE, argv[2], - "This file could not be opened. A valid file must be given."); - status = 1; - - return status; - } - else - fclose(infFile); - -#if 0 - ds_uninst_set_cgi_env(argv[2]); -#else - fprintf(stdout, "Call Uninstall\n"); -#endif - } else if (getenv("REQUEST_METHOD")) { /* case 2: called as a CGI */ - fprintf(stdout, "Content-type: text/html\n\n"); - fflush(stdout); - } else { /* case 3: run from the command line */ - /* when being run from the command line, we require many command line arguments */ - /* we need to do 2 or three things: - 1 - stop the server and remove the server instance directory - 2 - remove the server's information from the config ds - 3 - On Windows, remove the registry information - We require the instance name as an argument. We also need the following: - For 1, we need the server root - For 2, we need the config ds host, port, admin domain, admin dn, admin password - For 3, just the instance name - - There are two other arguments that are optional. -force will ignore errors and just keep - going. On Windows, -allreg will clean up all known registry information for all instances - of DS on this machine - */ - } - - - if ( init_ds_env() ) { - return 1; - } - - /* - * Get the server path to delete. - * serverpath = //slapd- - */ - if (!(servername = get_cgi_var("InstanceName", NULL, NULL))) - servername = ds_get_server_name(); - - /* Check again if the serevr is down or not */ - if((isRunning = ds_get_updown_status()) == DS_SERVER_UP) { - if ((status = ds_bring_down_server()) != DS_SERVER_DOWN) { - char buf[1024]; - PR_snprintf(buf, sizeof(buf), "Could not stop server: error %d", status); - ds_report_error (DS_GENERAL_FAILURE, servername, buf); - return 1; - } - } - - if (servername) { - char line[1024]; - int busy_retries = 3; /* if busy, retry this many times */ - instdir = ds_get_instance_dir(); - /* We may get busy errors if files are in use when we try - to remove them, so if that happens, sleep for 30 seconds - and try again */ - status = ds_rm_rf(instdir, rm_rf_err_func, NULL); - while (status && try_rm_rf_again && busy_retries) { - PR_snprintf(line, sizeof(line), "Some files or directories in %s are still in use. Will sleep for 30 seconds and try again.", - instdir); - ds_show_message(line); - PR_Sleep(PR_SecondsToInterval(30)); - try_rm_rf_again = 0; - --busy_retries; - status = ds_rm_rf(instdir, rm_rf_err_func, NULL); - } - if (status) { - PR_snprintf(line, sizeof(line), "Could not remove %s. Please check log messages and try again.", - instdir); - ds_send_error(line, 0); - } - } -#ifdef XP_WIN32 - if (servername) { - status += ds_remove_reg_key(HKEY_LOCAL_MACHINE, "%s\\%s\\%s\\%s", KEY_SOFTWARE_NETSCAPE, - DS_NAME_SHORT, DS_VERSION, servername); - - /* also try to remove version key in case this is the last instance */ - status += ds_remove_reg_key(HKEY_LOCAL_MACHINE, "%s\\%s\\%s", KEY_SOFTWARE_NETSCAPE, - DS_NAME_SHORT, DS_VERSION); - - /* also try to remove product key in case this is the last instance */ - status += ds_remove_reg_key(HKEY_LOCAL_MACHINE, "%s\\%s", KEY_SOFTWARE_NETSCAPE, - DS_NAME_SHORT); - - /* also need to remove service */ - if (!DeleteServer(servername)) { - status += 1; - } - - /* Remove Event Log Key */ - status += ds_remove_reg_key(HKEY_LOCAL_MACHINE, "%s\\%s\\%s", KEY_SERVICES, KEY_EVENTLOG_APP, servername); - } -#endif - - if (status == 0) { - char buf[1024]; - PR_snprintf(buf, sizeof(buf), "Server %s was successfully removed", servername); - ds_show_message(buf); - rpt_success(""); - } else { - char buf[1024]; - PR_snprintf(buf, sizeof(buf), "Could not remove server %s", servername); - ds_send_error(buf, 0); - } - - return status; -} diff --git a/include/libdsa/dsalib.h b/include/libdsa/dsalib.h index ff3f764..ffbde43 100644 --- a/include/libdsa/dsalib.h +++ b/include/libdsa/dsalib.h @@ -260,7 +260,8 @@ struct ldbm_data { #define DS_LOCALUSER 14 #define DS_BAKDIR 15 #define DS_TMPDIR 16 -#define DS_CFG_MAX 17 /* MUST be one greater than the last option */ +#define DS_INSTDIR 17 +#define DS_CFG_MAX 18 /* MUST be one greater than the last option */ /* These control how long we wait for the server to start up or shutdown */ #define SERVER_START_TIMEOUT 600 /* seconds */ @@ -446,11 +447,6 @@ extern DS_EXPORT_SYMBOL char *ds_system_errmsg(void); extern DS_EXPORT_SYMBOL int ds_exec_and_report(char *cmd); -/* remove a directory hierarchy - if the error function is given, it will be called upon - error (e.g. directory not readable, cannot remove file, etc.) - if the callback function - returns 0, this means to abort the removal, otherwise, continue -*/ -extern DS_EXPORT_SYMBOL int ds_rm_rf(const char *dir, DS_RM_RF_ERR_FUNC ds_rm_rf_err_func, void *arg); /* remove a registry key and report an error message if unsuccessful */ diff --git a/lib/libdsa/dsalib_conf.c b/lib/libdsa/dsalib_conf.c index bfaca4e..7c46cc0 100644 --- a/lib/libdsa/dsalib_conf.c +++ b/lib/libdsa/dsalib_conf.c @@ -104,6 +104,7 @@ struct ds_cfg_info ds_cfg_info[] = { {"nsslapd-localuser"}, {"nsslapd-bakdir"}, {"nsslapd-tmpdir"}, +{"nsslapd-instancedir"}, {0} }; diff --git a/lib/libdsa/dsalib_location.c b/lib/libdsa/dsalib_location.c index 05b990a..b631600 100644 --- a/lib/libdsa/dsalib_location.c +++ b/lib/libdsa/dsalib_location.c @@ -41,11 +41,11 @@ ds_get_instance_dir() char *ds_name; static char instance_dir[PATH_MAX]; - if ( (ds_name = ds_get_server_name()) == NULL ) + if ( (ds_name = ds_get_server_name()) == NULL ) { return(NULL); - - PR_snprintf(instance_dir, sizeof(instance_dir), "%s/%s", DSLIBDIR, ds_name); - return(instance_dir); + } else { + return ds_get_config_value(DS_INSTDIR); + } } /* @@ -90,12 +90,43 @@ ds_set_config_dir(char *config_dir) DS_EXPORT_SYMBOL char * ds_get_run_dir() { - char *rundir; + char *rundir_env = NULL; + static char rundir[PATH_MAX]; + char *inst_dir = NULL; + char *start_script = NULL; + char *p = NULL; + char line[BIG_LINE]; + FILE *fp = NULL; - if (rundir = getenv("DS_RUN_DIR")) { - return (rundir); + if (rundir_env = getenv("DS_RUN_DIR")) { + return (rundir_env); } else { - return (PIDDIR);; + /* Find the run dir from the start script */ + inst_dir = ds_get_instance_dir(); + start_script = PR_smprintf("%s%cstart-slapd", inst_dir, FILE_PATHSEP); + fp = fopen(start_script, "r"); + if (fp) { + while(fgets(line, BIG_LINE, fp)) { + /* Find line starting with PIDFILE */ + if (strncmp(line, "PIDFILE", 7) == 0) { + /* Chop off the pidfile name to get the run dir */ + if (p = strrchr(line, '/')) { + *p = '\0'; + PR_snprintf(rundir, sizeof(rundir), "%s", line + 8); + } + break; + } + } + fclose(fp); + } + + PR_smprintf_free(start_script); + + if (rundir[0] != '\0') { + return (rundir); + } else { + return NULL; + } } } diff --git a/lib/libdsa/dsalib_util.c b/lib/libdsa/dsalib_util.c index e60892b..e468402 100644 --- a/lib/libdsa/dsalib_util.c +++ b/lib/libdsa/dsalib_util.c @@ -52,8 +52,6 @@ static const char *SEPARATOR = ":"; /* from AdmTask.java */ #define LOGFILEENVVAR "DEBUG_LOGFILE" /* used for logfp */ -static int internal_rm_rf(const char *path, DS_RM_RF_ERR_FUNC ds_rm_rf_err_func, void *arg); - /* return a FILE * opened in append mode to the log file caller must use fclose to close it */ @@ -840,100 +838,6 @@ is_fullpath(char *path) return 0; } -static void -rm_db_dirs(char *fullpath, DS_RM_RF_ERR_FUNC ds_rm_rf_err_func, void *arg) -{ - FILE *fp = fopen(fullpath, "r"); - char buf[2][MAXPATHLEN]; - char *bufp, *nextbufp; - char *retp; - int readit = 0; - - if (fp == NULL) - { - ds_rm_rf_err_func(fullpath, "opening the config file", arg); - return; - } - - bufp = buf[0]; *bufp = '\0'; - nextbufp = buf[1]; *nextbufp = '\0'; - - while (readit || (retp = fgets(bufp, MAXPATHLEN, fp)) != NULL) - { - int len = strlen(bufp); - int type = -1; - char *p, *q; - - if (strstr(bufp, "nsslapd-directory")) - type = DB_DIRECTORY; - else if (strstr(bufp, "nsslapd-db-home-directory")) - type = DB_HOME_DIRECTORY; - else if (strstr(bufp, "nsslapd-db-logdirectory")) - type = DB_LOGDIRECTORY; - else if (strstr(bufp, "nsslapd-changelogdir")) - type = DB_CHANGELOGDIRECTORY; - else - { - readit = 0; - continue; - } - - p = bufp + len; - - while ((retp = fgets(nextbufp, MAXPATHLEN, fp)) != NULL) - { - int thislen; - if (*nextbufp == ' ') - { - thislen = strlen(nextbufp); - len += thislen; - if (len < MAXPATHLEN) - { - strncpy(p, nextbufp, thislen); - p += thislen; - } - /* else too long as a path. ignore it */ - } - else - break; - } - if (retp == NULL) /* done */ - break; - - p = strchr(bufp, ':'); - if (p == NULL) - { - char *tmpp = bufp; - bufp = nextbufp; - nextbufp = tmpp; - readit = 1; - continue; - } - - while (*(++p) == ' ') ; - - q = p + strlen(p) - 1; - while (*q == ' ' || *q == '\t' || *q == '\n') - q--; - *(q+1) = '\0'; - - switch (type) - { - case DB_DIRECTORY: - case DB_LOGDIRECTORY: - case DB_CHANGELOGDIRECTORY: - if (is_fullpath(p)) - internal_rm_rf(p, ds_rm_rf_err_func, NULL); - break; - case DB_HOME_DIRECTORY: - internal_rm_rf(p, ds_rm_rf_err_func, NULL); - break; - } - } - - fclose(fp); -} - static char * get_dir_from_startslapd(char *loc, char *keyword) { @@ -971,134 +875,6 @@ get_dir_from_config(char *config_dir, char *config_attr) return dir; } -/* this function will recursively remove a directory hierarchy from the file - system, like "rm -rf" - In order to handle errors, the user supplies a callback function. When an - error occurs, the callback function is called with the file or directory name - and the system errno. The callback function should return TRUE if it wants - to continue or FALSE if it wants the remove aborted. - The error callback should use PR_GetError and/or PR_GetOSError to - determine the cause of the failure -*/ -/* you could locate db dirs non standard location - we should remove them, as well. -*/ -static int -internal_rm_rf(const char *path, DS_RM_RF_ERR_FUNC ds_rm_rf_err_func, void *arg) -{ - struct PRFileInfo prfi; - int retval = 0; - - if (PR_GetFileInfo(path, &prfi) != PR_SUCCESS) { - if (!ds_rm_rf_err_func(path, "reading directory", arg)) { - return 1; - } - } - - if (prfi.type == PR_FILE_DIRECTORY) - { - PRDir *dir; - PRDirEntry *dirent; - - if (!(dir = PR_OpenDir(path))) { - if (!ds_rm_rf_err_func(path, "opening directory", arg)) { - return 1; - } - return 0; - } - - while ((dirent = PR_ReadDir(dir, PR_SKIP_BOTH))) { - char *fullpath = PR_smprintf("%s%c%s", path, FILE_PATHSEP, dirent->name); - if (PR_GetFileInfo(fullpath, &prfi) != PR_SUCCESS) { - if (!ds_rm_rf_err_func(fullpath, "reading file", arg)) { - PR_smprintf_free(fullpath); - PR_CloseDir(dir); - return 1; - } /* else just continue */ - } else if (prfi.type == PR_FILE_DIRECTORY) { - retval = internal_rm_rf(fullpath, ds_rm_rf_err_func, arg); - if (retval) { /* non zero return means stop */ - PR_smprintf_free(fullpath); - break; - } - } else { - /* FHS changes the directory structure. - * Config dir is no longer in the instance dir. - * The info should be found in start-slapd, - * therefore get the path from the file here. - */ - if (0 == strcmp(dirent->name, "start-slapd")) { - char *config_dir = ds_get_config_dir(); - char *run_dir = ds_get_run_dir(); - if (NULL == config_dir || '\0' == *config_dir) { - config_dir = get_dir_from_startslapd(fullpath, DS_CONFIG_DIR); - } - if (NULL == run_dir || '\0' == *run_dir) { - char *ptr = NULL; - run_dir = get_dir_from_startslapd(fullpath, PIDFILE); - ptr = strrchr(run_dir, FILE_PATHSEP); - if (NULL != ptr) { - *ptr = '\0'; /* equiv to dirname */ - } - } - if (NULL != run_dir) { - internal_rm_rf(run_dir, ds_rm_rf_err_func, NULL); - free(run_dir); - } - if (NULL != config_dir) { - char *lock_dir = get_dir_from_config(config_dir, DS_CONFIG_LOCKDIR); - char *err_log = get_dir_from_config(config_dir, DS_CONFIG_ERRLOG); - - if (NULL != lock_dir) { - internal_rm_rf(lock_dir, ds_rm_rf_err_func, NULL); - free(lock_dir); - } - if (NULL != err_log) { - char *ptr = strrchr(err_log, FILE_PATHSEP); - if (NULL != ptr) { - *ptr = '\0'; /* equiv to 'dirname' */ - internal_rm_rf(err_log, ds_rm_rf_err_func, NULL); - } - free(err_log); - } - /* removing db dirs */ - rm_db_dirs(config_dir, ds_rm_rf_err_func, arg); - - /* removing config dir */ - internal_rm_rf(config_dir, ds_rm_rf_err_func, NULL); - } - } - /* - * When the file is the config file, - * check if db dir is in the instance dir or not. - * If db dir exists in the instance dir, it's an old structure. - * Let's clean the old db here, as well. - */ - if (0 == strcmp(dirent->name, DS_CONFIG_FILE)) { - rm_db_dirs(fullpath, ds_rm_rf_err_func, arg); - } - - if (PR_Delete(fullpath) != PR_SUCCESS) { - if (!ds_rm_rf_err_func(fullpath, "deleting file", arg)) { - PR_smprintf_free(fullpath); - PR_CloseDir(dir); - return 1; - } - } - } - PR_smprintf_free(fullpath); - } - PR_CloseDir(dir); - if (PR_RmDir(path) != PR_SUCCESS) { - if (!ds_rm_rf_err_func(path, "removing directory", arg)) { - retval = 1; - } - } - } - - return retval; -} - static int default_err_func(const char *path, const char *op, void *arg) { @@ -1119,38 +895,6 @@ default_err_func(const char *path, const char *op, void *arg) return 1; /* just continue */ } -/* dir: instance dir, e.g., "$NETSITE_ROOT/slapd-" */ -DS_EXPORT_SYMBOL int -ds_rm_rf(const char *dir, DS_RM_RF_ERR_FUNC ds_rm_rf_err_func, void *arg) -{ - struct PRFileInfo prfi; - - if (!dir) { - ds_send_error("Could not remove NULL directory name", 1); - return 1; - } - - if (!ds_rm_rf_err_func) { - ds_rm_rf_err_func = default_err_func; - } - - if (PR_GetFileInfo(dir, &prfi) != PR_SUCCESS) { - if (ds_rm_rf_err_func(dir, "reading directory", arg)) { - return 0; - } else { - return 1; - } - } - if (prfi.type != PR_FILE_DIRECTORY) { - char *msg = PR_smprintf("Cannot remove directory %s because it is not a directory", dir); - ds_send_error(msg, 0); - PR_smprintf_free(msg); - return 1; - } - - return internal_rm_rf(dir, ds_rm_rf_err_func, arg); -} - DS_EXPORT_SYMBOL int ds_remove_reg_key(void *base, const char *format, ...) {