diff options
Diffstat (limited to 'ldap/admin/lib/dsalib_util.c')
-rw-r--r-- | ldap/admin/lib/dsalib_util.c | 1212 |
1 files changed, 0 insertions, 1212 deletions
diff --git a/ldap/admin/lib/dsalib_util.c b/ldap/admin/lib/dsalib_util.c deleted file mode 100644 index 0a0cfe0c..00000000 --- a/ldap/admin/lib/dsalib_util.c +++ /dev/null @@ -1,1212 +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. - * - * In addition, as a special exception, Red Hat, Inc. gives You the additional - * right to link the code of this Program with code not covered under the GNU - * General Public License ("Non-GPL Code") and to distribute linked combinations - * including the two, subject to the limitations in this paragraph. Non-GPL Code - * permitted under this exception must only link to the code of this Program - * through those well defined interfaces identified in the file named EXCEPTION - * found in the source code files (the "Approved Interfaces"). The files of - * Non-GPL Code may instantiate templates or use macros or inline functions from - * the Approved Interfaces without causing the resulting work to be covered by - * the GNU General Public License. Only Red Hat, Inc. may make changes or - * additions to the list of Approved Interfaces. You must obey the GNU General - * Public License in all respects for all of the Program code and other code used - * in conjunction with the Program except the Non-GPL Code covered by this - * exception. If you modify this file, you may extend this exception to your - * version of the file, but you are not obligated to do so. If you do not wish to - * provide this exception without modification, you must delete this exception - * statement from your version and license this file solely under the GPL without - * exception. - * - * - * 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 <config.h> -#endif - -#if defined( XP_WIN32 ) -#include <windows.h> -#include <io.h> -#else /* XP_WIN32 */ -# if defined( AIXV4 ) -# include <fcntl.h> -# else /* AIXV4 */ -# include <sys/fcntl.h> -# endif /* AIXV4 */ -#include <dirent.h> -#include <unistd.h> -#include <fcntl.h> -#endif /* XP_WIN3 */ -#include "dsalib.h" -#include <sys/types.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <ctype.h> - -#include "nspr.h" -#include "plstr.h" - -#define COPY_BUFFER_SIZE 4096 -/* This is the separator string to use when outputting key/value pairs - to be read by the non-HTML front end (Java console) -*/ -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 -*/ -static FILE * -get_logfp(void) -{ - FILE *logfp = NULL; - char *logfile = getenv(LOGFILEENVVAR); - - if (logfile) { - logfp = fopen(logfile, "a"); - } - return logfp; -} - -DS_EXPORT_SYMBOL int -ds_file_exists(char *filename) -{ - struct stat finfo; - - if ( filename == NULL ) - return 0; - - if ( stat(filename, &finfo) == 0 ) /* successful */ - return 1; - else - return 0; -} - -DS_EXPORT_SYMBOL int -ds_mkdir(char *dir, int mode) -{ - if(!ds_file_exists(dir)) { -#ifdef XP_UNIX - if(mkdir(dir, mode) == -1) -#else /* XP_WIN32 */ - if(!CreateDirectory(dir, NULL)) -#endif /* XP_WIN32 */ - return -1; - } - return 0; -} - - -DS_EXPORT_SYMBOL char * -ds_mkdir_p(char *dir, int mode) -{ - static char errmsg[ERR_SIZE]; - struct stat fi; - char *t; - -#ifdef XP_UNIX - t = dir + 1; -#else /* XP_WIN32 */ - t = dir + 3; -#endif /* XP_WIN32 */ - - while(1) { - t = strchr(t, FILE_PATHSEP); - - if(t) *t = '\0'; - if(stat(dir, &fi) == -1) { - if(ds_mkdir(dir, mode) == -1) { - PR_snprintf(errmsg, sizeof(errmsg), "mkdir %s failed (%s)", dir, ds_system_errmsg()); - return errmsg; - } - } - if(t) *t++ = FILE_PATHSEP; - else break; - } - return NULL; -} - - -/* - * Given the name of a directory, return a NULL-terminated array of - * the file names contained in that directory. Returns NULL if the directory - * does not exist or an error occurs, and returns an array with a - * single NULL string if the directory exists but is empty. The caller - * is responsible for freeing the returned array of strings. - * File names "." and ".." are not returned. - */ -#if !defined( XP_WIN32 ) -DS_EXPORT_SYMBOL char ** -ds_get_file_list( char *dir ) -{ - DIR *dirp; - struct dirent *direntp; - char **ret = NULL; - int nfiles = 0; - - if (( dirp = opendir( dir )) == NULL ) { - return NULL; - } - - if (( ret = malloc( sizeof( char * ))) == NULL ) { - return NULL; - }; - - while (( direntp = readdir( dirp )) != NULL ) { - if ( strcmp( direntp->d_name, "." ) && - strcmp( direntp->d_name, ".." )) { - if (( ret = (char **) realloc( ret, - sizeof( char * ) * ( nfiles + 2 ))) == NULL ); - ret[ nfiles ] = strdup( direntp->d_name ); - nfiles++; - } - } - (void) closedir( dirp ); - - ret[ nfiles ] = NULL; - return ret; -} -#else -DS_EXPORT_SYMBOL char ** -ds_get_file_list( char *dir ) -{ - char szWildcardFileSpec[MAX_PATH]; - char **ret = NULL; - long hFile; - struct _finddata_t fileinfo; - int nfiles = 0; - - if( ( dir == NULL ) || (strlen( dir ) == 0) ) - return NULL; - - if( ( ret = malloc( sizeof( char * ) ) ) == NULL ) - return NULL; - - PL_strncpyz(szWildcardFileSpec, dir, sizeof(szWildcardFileSpec)); - PL_strcatn(szWildcardFileSpec, sizeof(szWildcardFileSpec), "/*"); - - hFile = _findfirst( szWildcardFileSpec, &fileinfo); - if( hFile == -1 ) - return NULL; - - if( ( strcmp( fileinfo.name, "." ) != 0 ) && - ( strcmp( fileinfo.name, ".." ) != 0 ) ) - { - ret[ nfiles++ ] = strdup( fileinfo.name ); - } - - while( _findnext( hFile, &fileinfo ) == 0 ) - { - if( ( strcmp( fileinfo.name, "." ) != 0 ) && - ( strcmp( fileinfo.name, ".." ) != 0 ) ) - { - if( ( ret = (char **) realloc( ret, sizeof( char * ) * ( nfiles + 2 ) ) ) != NULL ) - ret[ nfiles++ ] = strdup( fileinfo.name); - } - } - - _findclose( hFile ); - ret[ nfiles ] = NULL; - return ret; -} -#endif /* ( XP_WIN32 ) */ - - -DS_EXPORT_SYMBOL time_t -ds_get_mtime(char *filename) -{ - struct stat fi; - - if ( stat(filename, &fi) ) - return 0; - return fi.st_mtime; -} - -/* - * Copy files: return is - * 1: success - * 0: failure - * Print errors as needed. - */ -DS_EXPORT_SYMBOL int -ds_cp_file(char *sfile, char *dfile, int mode) -{ -#if defined( XP_WIN32 ) - return( CopyFile( sfile, dfile, FALSE ) ); /* Copy even if dfile exists */ -#else - int sfd, dfd, len; - struct stat fi; - char copy_buffer[COPY_BUFFER_SIZE]; - unsigned long read_len; - char error[BIG_LINE]; - -/* Make sure we're in the right umask */ - umask(022); - - if( (sfd = open(sfile, O_RDONLY)) == -1) { - PR_snprintf(error, sizeof(error), "Can't open file %s for reading.", sfile); - ds_send_error(error, 1); - return(0); - } - - fstat(sfd, &fi); - if (!(S_ISREG(fi.st_mode))) { - PR_snprintf(error, sizeof(error), "File %s is not a regular file.", sfile); - ds_send_error(error, 1); - close(sfd); - return(0); - } - len = fi.st_size; - - if( (dfd = open(dfile, O_RDWR | O_CREAT | O_TRUNC, mode)) == -1) { - PR_snprintf(error, sizeof(error), "can't write to file %s", dfile); - ds_send_error(error, 1); - close(sfd); - return(0); - } - while (len) { - read_len = len>COPY_BUFFER_SIZE?COPY_BUFFER_SIZE:len; - - if ( (read_len = read(sfd, copy_buffer, read_len)) == -1) { - PR_snprintf(error, sizeof(error), "Error reading file %s for copy.", sfile); - ds_send_error(error, 1); - close(sfd); - close(dfd); - return(0); - } - - if ( write(dfd, copy_buffer, read_len) != read_len) { - PR_snprintf(error, sizeof(error), "Error writing file %s for copy.", dfile); - ds_send_error(error, 1); - close(sfd); - close(dfd); - return(0); - } - - len -= read_len; - } - close(sfd); - close(dfd); - return(1); -#endif -} - -DS_EXPORT_SYMBOL void -ds_unixtodospath(char *szText) -{ - if(szText) - { - while(*szText) - { - if( *szText == '/' ) - *szText = '\\'; - szText++; - } - } -} - -/* converts '\' chars to '/' */ -DS_EXPORT_SYMBOL void -ds_dostounixpath(char *szText) -{ - if(szText) - { - while(*szText) - { - if( *szText == '\\' ) - *szText = '/'; - szText++; - } - } -} - -/* converts ':' chars to ' ' */ -DS_EXPORT_SYMBOL void -ds_timetofname(char *szText) -{ - if(szText) - { - /* Replace trailing newline */ - szText[ strlen( szText ) -1 ] = 0; - while(*szText) - { - if( *szText == ':' || - *szText == ' ' ) - *szText = '_'; - szText++; - } - } -} - -/* Effects a rename in 2 steps, needed on NT because if the -target of a rename() already exists, the rename() will fail. */ -DS_EXPORT_SYMBOL int -ds_saferename(char *szSrc, char *szTarget) -{ -#ifdef XP_WIN32 - int iRetVal; - char *szTmpFile; - struct stat buf; -#endif - - if( !szSrc || !szTarget ) - return 1; - -#if defined( XP_WIN32 ) - - szTmpFile = mktemp("slrnXXXXXX" ); - if( stat( szTarget, &buf ) == 0 ) - { - /* Target file exists */ - if( !szTmpFile ) - return 1; - - if( !ds_cp_file( szTarget, szTmpFile, 0644) ) - return( 1 ); - - unlink( szTarget ); - if( (iRetVal = rename( szSrc, szTarget )) != 0 ) - { - /* Failed to rename, copy back. */ - ds_cp_file( szTmpFile, szTarget, 0644); - } - /* Now remove temp file */ - unlink( szTmpFile ); - } - else - iRetVal = rename(szSrc, szTarget); - - return iRetVal; -#else - return rename(szSrc, szTarget); -#endif - -} - -DS_EXPORT_SYMBOL char* -ds_encode_all (const char* s) -{ - char* r; - size_t l; - size_t i; - if (s == NULL || *s == '\0') { - return strdup (""); - } - l = strlen (s); - r = malloc (l * 3 + 1); - for (i = 0; *s != '\0'; ++s) { - r[i++] = '%'; - sprintf (r + i, "%.2X", 0xFF & (unsigned int)*s); - i += 2; - } - r[i] = '\0'; - return r; -} - -DS_EXPORT_SYMBOL char* -ds_URL_encode (const char* s) -{ - char* r; - size_t l; - size_t i; - if (s == NULL || *s == '\0') { - return strdup (""); - } - l = strlen (s) + 1; - r = malloc (l); - for (i = 0; *s != '\0'; ++s) { - if (*s >= 0x20 && *s <= 0x7E && strchr (" <>\"#%{}[]|\\^~`?,;=+\n", *s) == NULL) { - if (l - i <= 1) r = realloc (r, l *= 2); - r[i++] = *s; - } else { /* encode *s */ - if (l - i <= 3) r = realloc (r, l *= 2); - r[i++] = '%'; - sprintf (r + i, "%.2X", 0xFF & (unsigned int)*s); - i += 2; - } - } - r[i] = '\0'; - return r; -} - -DS_EXPORT_SYMBOL char* -ds_URL_decode (const char* original) -{ - char* r = strdup (original); - char* s; - for (s = r; *s != '\0'; ++s) { - if (*s == '+') { - *s = ' '; - } - else if (*s == '%' && isxdigit(s[1]) && isxdigit(s[2])) { - memmove (s, s+1, 2); - s[2] = '\0'; - *s = (char)strtoul (s, NULL, 16); - memmove (s+1, s+3, strlen (s+3) + 1); - } - } - return r; -} - -#if !defined( XP_WIN32 ) -#include <errno.h> /* errno */ -#include <pwd.h> /* getpwnam */ - -static int saved_uid_valid = 0; -static uid_t saved_uid; -static int saved_gid_valid = 0; -static gid_t saved_gid; - -#if defined( HPUX ) -#define SETEUID(id) setresuid((uid_t) -1, id, (uid_t) -1) -#else -#define SETEUID(id) seteuid(id) -#endif - -#endif - -DS_EXPORT_SYMBOL char* -ds_become_localuser_name (char *localuser) -{ -#if !defined( XP_WIN32 ) - if (localuser != NULL) { - struct passwd* pw = getpwnam (localuser); - if (pw == NULL) { - fprintf (stderr, "getpwnam(%s) == NULL; errno %d", - localuser, errno); - fprintf (stderr, "\n"); - fflush (stderr); - } else { - if ( ! saved_uid_valid) saved_uid = geteuid(); - if ( ! saved_gid_valid) saved_gid = getegid(); - if (setgid (pw->pw_gid) == 0) { - saved_gid_valid = 1; - } else { - fprintf (stderr, "setgid(%li) != 0; errno %d", - (long)pw->pw_gid, errno); - fprintf (stderr, "\n"); - fflush (stderr); - } - if (SETEUID (pw->pw_uid) == 0) { - saved_uid_valid = 1; - } else { - fprintf (stderr, "seteuid(%li) != 0; errno %d", - (long)pw->pw_uid, errno); - fprintf (stderr, "\n"); - fflush (stderr); - } - } - } - return NULL; -#else - return NULL; -#endif -} - -DS_EXPORT_SYMBOL char* -ds_become_localuser (char **ds_config) -{ -#if !defined( XP_WIN32 ) - char* localuser = ds_get_value (ds_config, ds_get_var_name(DS_LOCALUSER), 0, 1); - if (localuser != NULL) { - char *rv = ds_become_localuser_name(localuser); - - free(localuser); - return rv; - } - return NULL; -#else - return NULL; -#endif -} - -DS_EXPORT_SYMBOL char* -ds_become_original (char **ds_config) -{ -#if !defined( XP_WIN32 ) - if (saved_uid_valid) { - if (SETEUID (saved_uid) == 0) { - saved_uid_valid = 0; - } else { - fprintf (stderr, "seteuid(%li) != 0; errno %d<br>n", - (long)saved_uid, errno); - fflush (stderr); - } - } - if (saved_gid_valid) { - if (setgid (saved_gid) == 0) { - saved_gid_valid = 0; - } else { - fprintf (stderr, "setgid(%li) != 0; errno %d<br>\n", - (long)saved_gid, errno); - fflush (stderr); - } - } - return NULL; -#else - return NULL; -#endif -} - -/* - * When a path containing a long filename is passed to system(), the call - * fails. Therfore, we need to use the short version of the path, when - * constructing the path to pass to system(). - */ -DS_EXPORT_SYMBOL char* -ds_makeshort( char * filepath ) -{ -#if defined( XP_WIN32 ) - char *shortpath = malloc( MAX_PATH ); - DWORD dwStatus; - if( shortpath ) - { - dwStatus = GetShortPathName( filepath, shortpath, MAX_PATH ); - return( shortpath ); - } -#endif - return filepath; -} - -/* returns 1 if string "searchstring" found in file "filename" */ -/* if found, returnstring is allocated and filled with the line */ -/* caller should release the memory */ -DS_EXPORT_SYMBOL int -ds_search_file(char *filename, char *searchstring, char **returnstring) -{ - struct stat finfo; - FILE * sf; - char big_line[BIG_LINE]; - - if( filename == NULL ) - return 0; - - if( stat(filename, &finfo) != 0 ) /* successful */ - return 0; - - if( !(sf = fopen(filename, "r")) ) - return 0; - - while ( fgets(big_line, BIG_LINE, sf) ) { - if( strstr( big_line, searchstring ) != NULL ) { - *returnstring = (char *)malloc(strlen(big_line) + 1); - if (NULL != *returnstring) { - strcpy(*returnstring, big_line); - } - fclose(sf); - return 1; - } - } - - fclose(sf); - - return 0; -} - -/* - * on linux when running as root, doing something like - * system("date > out.log 2>&1") will fail, because of an - * ambigious redirect. This works for /bin/sh, but not /bin/csh or /bin/tcsh - * - * using this would turn - * system("date > out.log 2>&1"); - * into - * system("/bin/sh/ -c \"date > out.log 2>&1\"") - * - */ -DS_EXPORT_SYMBOL void -alter_startup_line(char *startup_line) -{ -#if (defined Linux && !defined LINUX2_4) - char temp_startup_line[BIG_LINE+40]; - - PR_snprintf(temp_startup_line, sizeof(temp_startup_line), "/bin/sh -c \"%s\"", startup_line); - PL_strncpyz(startup_line, temp_startup_line, BIG_LINE); -#else - /* do nothing */ -#endif /* Linux */ -} - -DS_EXPORT_SYMBOL void -ds_send_error(char *errstr, int print_errno) -{ - FILE *logfp; - fprintf(stdout, "error%s%s\n", SEPARATOR, errstr); - if (print_errno && errno) - fprintf(stdout, "system_errno%s%d\n", SEPARATOR, errno); - - fflush(stdout); - - if ((logfp = get_logfp())) { - fprintf(logfp, "error%s%s\n", SEPARATOR, errstr); - if (print_errno && errno) - fprintf(logfp, "system_errno%s%d\n", SEPARATOR, errno); - fclose(logfp); - } - -} - -DS_EXPORT_SYMBOL void -ds_send_status(char *str) -{ - FILE *logfp; - fprintf(stdout, "[%s]: %s\n", ds_get_server_name(), str); - fflush(stdout); - - if ((logfp = get_logfp())) { - fprintf(logfp, "[%s]: %s\n", ds_get_server_name(), str); - fclose(logfp); - } -} - -/* type and doexit are unused - I'm not sure what type is supposed to be used for - removed the doexit code because we don't want to - exit abruptly anymore, we must exit by returning an - exit code from the return in main() -*/ -static void -report_error(int type, char *msg, char *details, int doexit) -{ - char error[BIG_LINE*4] = {0}; - - if (msg) - { - PL_strcatn(error, BIG_LINE*4, msg); - PL_strcatn(error, BIG_LINE*4, SEPARATOR); - } - if (details) - PL_strcatn(error, BIG_LINE*4, details); - ds_send_error(error, 1); -} - -DS_EXPORT_SYMBOL void -ds_report_error(int type, char *msg, char *details) -{ - /* richm - changed exit flag to 0 - we must not exit - abruptly, we should instead exit by returning a code - as the return value of main - this ensures that callers - are properly notified of the status - */ - report_error(type, msg, details, 0); -} - -DS_EXPORT_SYMBOL void -ds_report_warning(int type, char *msg, char *details) -{ - report_error(type, msg, details, 0); -} - -DS_EXPORT_SYMBOL void -ds_show_message(const char *message) -{ - FILE *logfp; - printf("%s\n", message); - fflush(stdout); - - if ((logfp = get_logfp())) { - fprintf(logfp, "%s\n", message); - fclose(logfp); - } - - return; -} - -DS_EXPORT_SYMBOL void -ds_show_key_value(char *key, char *value) -{ - FILE *logfp; - printf("%s%s%s\n", key, SEPARATOR, value); - - if ((logfp = get_logfp())) { - fprintf(logfp, "%s%s%s\n", key, SEPARATOR, value); - fclose(logfp); - } - return; -} - -/* Stolen from the Admin Server dsgw_escape_for_shell */ -DS_EXPORT_SYMBOL char * -ds_escape_for_shell( char *s ) -{ - char *escaped; - char tmpbuf[4]; - size_t x,l; - - if ( s == NULL ) { - return( s ); - } - - l = 3 * strlen( s ) + 1; - escaped = malloc( l ); - memset( escaped, 0, l ); - for ( x = 0; s[x]; x++ ) { - if (( (unsigned char)s[x] & 0x80 ) == 0 ) { - strncat( escaped, &s[x], 1 ); - } else { - /* not an ASCII character - escape it */ - sprintf( tmpbuf, "\\%x", (unsigned)(((unsigned char)(s[x])) & 0xff) ); - strcat( escaped, tmpbuf ); - } - } - return( escaped ); -} - -DS_EXPORT_SYMBOL char * -ds_system_errmsg(void) -{ - static char static_error[BUFSIZ]; - char *lmsg = 0; /* Local message pointer */ - size_t msglen = 0; - int sys_error = 0; -#ifdef XP_WIN32 - LPTSTR sysmsg = 0; -#endif - - /* Grab the OS error message */ -#ifdef XP_WIN32 - sys_error = GetLastError(); -#else - sys_error = errno; -#endif - -#if defined(XP_WIN32) - msglen = FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, - GetLastError(), - LOCALE_SYSTEM_DEFAULT, - (LPTSTR)&sysmsg, - 0, - 0); - if (msglen > 0) - lmsg = sysmsg; - SetLastError(0); -#else - lmsg = strerror(errno); - errno = 0; -#endif - - if (!lmsg) - static_error[0] = 0; - else - { - /* At this point lmsg points to something. */ - int min = 0; - msglen = strlen(lmsg); - - min = msglen > BUFSIZ ? BUFSIZ : msglen; - strncpy(static_error, lmsg, min-1); - static_error[min-1] = 0; - } - -#ifdef XP_WIN32 - /* NT's FormatMessage() dynamically allocated the msg; free it */ - if (sysmsg) - LocalFree(sysmsg); -#endif - - return static_error; -} - -#ifndef MAXPATHLEN -#define MAXPATHLEN 1024 -#endif - -enum { - DB_DIRECTORY = 0, - DB_LOGDIRECTORY, - DB_CHANGELOGDIRECTORY, - DB_HOME_DIRECTORY -}; - -static int -is_fullpath(char *path) -{ - int len; - if (NULL == path || '\0' == *path) - return 0; - - if (FILE_PATHSEP == *path) /* UNIX */ - return 1; - - len = strlen(path); - if (len > 2) - { - if (':' == path[1] && ('/' == path[2] || '\\' == path[2])) /* Windows */ - return 1; - } - 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) -{ - char *returnstr = NULL; - char *ptr = NULL; - char *confdir = NULL; -if (ds_search_file(loc, keyword, &returnstr) > 0 && returnstr) { - ptr = strchr(returnstr, '='); - if (NULL != ptr) { - confdir = strdup(++ptr); - } - free(returnstr); - } - return confdir; -} - -static char * -get_dir_from_config(char *config_dir, char *config_attr) -{ - char *configfile = NULL; - char *returnstr = NULL; - char *ptr = NULL; - char *dir = NULL; - configfile = PR_smprintf("%s%c%s", config_dir, FILE_PATHSEP, DS_CONFIG_FILE); - if (configfile && ds_search_file(configfile, config_attr, &returnstr) > 0 - && returnstr) { - ptr = strchr(returnstr, ':'); - if (NULL != ptr) { - while (' ' == *ptr || '\t' == *ptr) ptr++; - dir = strdup(ptr); - } - free(returnstr); - PR_smprintf_free(configfile); - } - 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) -{ - 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); - } - - msg = PR_smprintf("%s %s: error code %d (%s)", op, path, errcode, errtext); - ds_send_error(msg, 0); - PR_smprintf_free(msg); - return 1; /* just continue */ -} - -/* dir: instance dir, e.g., "$NETSITE_ROOT/slapd-<id>" */ -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, ...) -{ - int rc = 0; -#ifdef XP_WIN32 - int retries = 3; - HKEY hkey = (HKEY)base; - char *key; - va_list ap; - - va_start(ap, format); - key = PR_vsmprintf(format, ap); - va_end(ap); - - do { - if (ERROR_SUCCESS != RegDeleteKey(hkey, key)) { - rc = GetLastError(); - if (rc == ERROR_BADKEY || rc == ERROR_CANTOPEN || - rc == ERROR_CANTREAD || - rc == ERROR_CANTWRITE || rc == ERROR_KEY_DELETED || - rc == ERROR_ALREADY_EXISTS || rc == ERROR_NO_MORE_FILES) { - rc = 0; /* key already deleted - no error */ - } else if ((retries > 1) && (rc == ERROR_IO_PENDING)) { - /* the key is busy - lets wait and try again */ - PR_Sleep(PR_SecondsToInterval(3)); - retries--; - } else { - char *errmsg = PR_smprintf("Could not remove registry key %s - error %d (%s)", - key, rc, ds_system_errmsg()); - ds_send_error(errmsg, 0); - PR_smprintf_free(errmsg); - break; /* no retry, just fail */ - } - } - } while (rc && retries); - PR_smprintf_free(key); -#endif - return rc; -} |