summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorTimothy Smith <timothy.smith@sun.com>2008-06-24 19:25:23 -0600
committerTimothy Smith <timothy.smith@sun.com>2008-06-24 19:25:23 -0600
commitbbe19e1360ec5b7dd33721b3cf19c6275c172021 (patch)
tree3d43edb300e41e75d201f36e255d247615807eb0 /mysys
parentc1a597cdf6daf2cde246453e23581d781799bd7d (diff)
downloadmariadb-git-bbe19e1360ec5b7dd33721b3cf19c6275c172021.tar.gz
Bug #20748: Configuration files should not be read more than once
Normalize directory names before adding them to default_directories. mysys/default.c: Normalize directory names with unpack_dirname() before adding them to default_directories. This way, /etc/ and /etc will not count as duplicates. Because this entails allocating memory to store the normalized names, add error handling and ensure that it doesn't leak memory in case both my_print_defaults() and load_defaults() are called. Clean up the Windows code that finds the exe's parent directory, and pull it out into a separate function. Reorganize the code into a single init_default_directories() function, with internal #ifdefs, instead of init_default_directories_<system>() functions which were accessed via a function pointer. This is more in line with normal MySQL coding style, and easier to read for some.
Diffstat (limited to 'mysys')
-rw-r--r--mysys/default.c284
1 files changed, 129 insertions, 155 deletions
diff --git a/mysys/default.c b/mysys/default.c
index e58903d6d64..eb7721acaed 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -48,13 +48,12 @@ char *my_defaults_extra_file=0;
/* Which directories are searched for options (and in which order) */
#define MAX_DEFAULT_DIRS 6
-const char *default_directories[MAX_DEFAULT_DIRS + 1];
+#define DEFAULT_DIRS_SIZE (MAX_DEFAULT_DIRS + 1) /* Terminate with NULL */
+static const char **default_directories = NULL;
#ifdef __WIN__
static const char *f_extensions[]= { ".ini", ".cnf", 0 };
#define NEWLINE "\r\n"
-static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN],
- config_dir[FN_REFLEN];
#else
static const char *f_extensions[]= { ".cnf", 0 };
#define NEWLINE "\n"
@@ -85,19 +84,34 @@ static int search_default_file_with_ext(Process_option_func func,
const char *config_file, int recursion_level);
-
/**
Create the list of default directories.
+ @param alloc MEM_ROOT where the list of directories is stored
+
@details
+ The directories searched, in order, are:
+ - Windows: GetSystemWindowsDirectory()
+ - Windows: GetWindowsDirectory()
+ - Windows: C:/
+ - Windows: Directory above where the executable is located
+ - Netware: sys:/etc/
+ - Unix & OS/2: /etc/
+ - Unix: --sysconfdir=<path> (compile-time option)
+ - OS/2: getenv(ETC)
+ - ALL: getenv(DEFAULT_HOME_ENV)
+ - ALL: --defaults-extra-file=<path> (run-time option)
+ - Unix: ~/
+
On all systems, if a directory is already in the list, it will be moved
to the end of the list. This avoids reading defaults files multiple times,
while ensuring the correct precedence.
- @return void
+ @retval NULL Failure (out of memory, probably)
+ @retval other Pointer to NULL-terminated array of default directories
*/
-static void (*init_default_directories)();
+static const char **init_default_directories(MEM_ROOT *alloc);
static char *remove_end_comment(char *ptr);
@@ -386,8 +400,9 @@ int load_defaults(const char *conf_file, const char **groups,
struct handle_option_ctx ctx;
DBUG_ENTER("load_defaults");
- init_default_directories();
init_alloc_root(&alloc,512,0);
+ if ((default_directories= init_default_directories(&alloc)) == NULL)
+ goto err;
/*
Check if the user doesn't want any default option processing
--no-defaults is always the first option
@@ -864,34 +879,49 @@ void my_print_default_files(const char *conf_file)
my_bool have_ext= fn_ext(conf_file)[0] != 0;
const char **exts_to_use= have_ext ? empty_list : f_extensions;
char name[FN_REFLEN], **ext;
- const char **dirs;
- init_default_directories();
puts("\nDefault options are read from the following files in the given order:");
if (dirname_length(conf_file))
fputs(conf_file,stdout);
else
{
- for (dirs=default_directories ; *dirs; dirs++)
+ /*
+ If default_directories is already initialized, use it. Otherwise,
+ use a private MEM_ROOT.
+ */
+ const char **dirs = default_directories;
+ MEM_ROOT alloc;
+ init_alloc_root(&alloc,512,0);
+
+ if (!dirs && (dirs= init_default_directories(&alloc)) == NULL)
{
- for (ext= (char**) exts_to_use; *ext; ext++)
+ fputs("Internal error initializing default directories list", stdout);
+ }
+ else
+ {
+ for ( ; *dirs; dirs++)
{
- const char *pos;
- char *end;
- if (**dirs)
- pos= *dirs;
- else if (my_defaults_extra_file)
- pos= my_defaults_extra_file;
- else
- continue;
- end= convert_dirname(name, pos, NullS);
- if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
- *end++='.';
- strxmov(end, conf_file, *ext, " ", NullS);
- fputs(name,stdout);
+ for (ext= (char**) exts_to_use; *ext; ext++)
+ {
+ const char *pos;
+ char *end;
+ if (**dirs)
+ pos= *dirs;
+ else if (my_defaults_extra_file)
+ pos= my_defaults_extra_file;
+ else
+ continue;
+ end= convert_dirname(name, pos, NullS);
+ if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
+ *end++= '.';
+ strxmov(end, conf_file, *ext, " ", NullS);
+ fputs(name, stdout);
+ }
}
}
+
+ free_root(&alloc, MYF(0));
}
puts("");
}
@@ -928,32 +958,23 @@ void print_defaults(const char *conf_file, const char **groups)
#include <help_end.h>
-/*
- This extra complexity is to avoid declaring 'rc' if it won't be
- used.
-*/
-#define ADD_DIRECTORY_INTERNAL(DIR) \
- array_append_string_unique((DIR), default_directories, \
- array_elements(default_directories))
-#ifdef DBUG_OFF
-# define ADD_DIRECTORY(DIR) (void) ADD_DIRECTORY_INTERNAL(DIR)
-#else
-#define ADD_DIRECTORY(DIR) \
- do { \
- my_bool rc= ADD_DIRECTORY_INTERNAL(DIR); \
- DBUG_ASSERT(rc == FALSE); /* Success */ \
- } while (0)
-#endif
-
+static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs)
+{
+ char buf[FN_REFLEN];
+ uint len;
+ char *p;
+ my_bool err __attribute__((unused));
+
+ /* Normalize directory name */
+ len= unpack_dirname(buf, dir);
+ if (!(p= strmake_root(alloc, buf, len)))
+ return 1; /* Failure */
+ /* Should never fail if DEFAULT_DIRS_SIZE is correct size */
+ err= array_append_string_unique(p, dirs, DEFAULT_DIRS_SIZE);
+ DBUG_ASSERT(err == FALSE);
-#define ADD_COMMON_DIRECTORIES() \
- do { \
- char *env; \
- if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) \
- ADD_DIRECTORY(env); \
- /* Placeholder for --defaults-extra-file=<path> */ \
- ADD_DIRECTORY(""); \
- } while (0)
+ return 0;
+}
#ifdef __WIN__
@@ -992,138 +1013,91 @@ static uint my_get_system_windows_directory(char *buffer, uint size)
}
-/**
- Initialize default directories for Microsoft Windows
-
- @details
- 1. GetSystemWindowsDirectory()
- 2. GetWindowsDirectory()
- 3. C:/
- 4. Directory above where the executable is located
- 5. getenv(DEFAULT_HOME_ENV)
- 6. --defaults-extra-file=<path> (run-time option)
-*/
-
-static void init_default_directories_win()
+static const char *my_get_module_parent(char *buf, size_t size)
{
- bzero((char *) default_directories, sizeof(default_directories));
-
- if (my_get_system_windows_directory(shared_system_dir,
- sizeof(shared_system_dir)))
- ADD_DIRECTORY(shared_system_dir);
-
- if (GetWindowsDirectory(system_dir,sizeof(system_dir)))
- ADD_DIRECTORY(system_dir);
+ if (!GetModuleFileName(NULL, buf, size))
+ return NULL;
- ADD_DIRECTORY("C:/");
-
- if (GetModuleFileName(NULL, config_dir, sizeof(config_dir)))
+ char *last= NULL, *end= strend(buf);
+ /*
+ Look for the second-to-last \ in the filename, but hang on
+ to a pointer after the last \ in case we're in the root of
+ a drive.
+ */
+ for ( ; end > buf; end--)
{
- char *last= NULL, *end= strend(config_dir);
- /*
- Look for the second-to-last \ in the filename, but hang on
- to a pointer after the last \ in case we're in the root of
- a drive.
- */
- for ( ; end > config_dir; end--)
+ if (*end == FN_LIBCHAR)
{
- if (*end == FN_LIBCHAR)
+ if (last)
{
- if (last)
- {
- if (end != config_dir)
- {
- /* Keep the last '\' as this works both with D:\ and a directory */
- end[1]= 0;
- }
- else
- {
- /* No parent directory (strange). Use current dir + '\' */
- last[1]= 0;
- }
- break;
- }
- last= end;
+ /* Keep the last '\' as this works both with D:\ and a directory */
+ end[1]= 0;
+ break;
}
+ last= end;
}
- ADD_DIRECTORY(config_dir);
}
- ADD_COMMON_DIRECTORIES();
+ return buf;
}
+#endif /* __WIN__ */
-static void (*init_default_directories)()= init_default_directories_win;
-
-#elif defined(__NETWARE__)
-
-/**
- Initialize default directories for Novell Netware
- @details
- 1. sys:/etc/
- 2. getenv(DEFAULT_HOME_ENV)
- 3. --defaults-extra-file=<path> (run-time option)
-*/
-
-static void init_default_directories_netware()
+static const char **init_default_directories(MEM_ROOT *alloc)
{
- bzero((char *) default_directories, sizeof(default_directories));
- ADD_DIRECTORY("sys:/etc/");
- ADD_COMMON_DIRECTORIES();
-}
+ const char **dirs;
+ char *env;
+ int errors= 0;
-static void (*init_default_directories)()= init_default_directories_netware;
+ dirs= (const char **)alloc_root(alloc, DEFAULT_DIRS_SIZE * sizeof(char *));
+ if (dirs == NULL)
+ return NULL;
+ bzero((char *) dirs, DEFAULT_DIRS_SIZE * sizeof(char *));
-#elif defined(__EMX__) || defined(OS2)
+#ifdef __WIN__
-/**
- Initialize default directories for OS/2
+ {
+ char fname_buffer[FN_REFLEN];
+ if (my_get_system_windows_directory(fname_buffer, sizeof(fname_buffer)))
+ errors += add_directory(alloc, fname_buffer, dirs);
- @details
- 1. /etc/
- 2. getenv(ETC)
- 3. getenv(DEFAULT_HOME_ENV)
- 4. --defaults-extra-file=<path> (run-time option)
-*/
+ if (GetWindowsDirectory(fname_buffer, sizeof(fname_buffer)))
+ errors += add_directory(alloc, fname_buffer, dirs);
-static void init_default_directories_os2()
-{
- const char *env;
+ errors += add_directory(alloc, "C:/", dirs);
- bzero((char *) default_directories, sizeof(default_directories));
- ADD_DIRECTORY("/etc/");
- if ((env= getenv("ETC")))
- ADD_DIRECTORY(env);
- ADD_COMMON_DIRECTORIES();
-}
+ if (my_get_module_parent(fname_buffer, sizeof(fname_buffer)) != NULL)
+ errors += add_directory(alloc, fname_buffer, dirs);
+ }
-static void (*init_default_directories)()= init_default_directories_os2;
+#elif defined(__NETWARE__)
-#else
+ errors += add_directory(alloc, "sys:/etc/", dirs);
-/**
- Initialize default directories for Unix
+#else
- @details
- 1. /etc/
- 2. --sysconfdir=<path> (compile-time option)
- 3. getenv(DEFAULT_HOME_ENV)
- 4. --defaults-extra-file=<path> (run-time option)
- 5. "~/"
-*/
+ errors += add_directory(alloc, "/etc/", dirs);
-static void init_default_directories_unix()
-{
- bzero((char *) default_directories, sizeof(default_directories));
- ADD_DIRECTORY("/etc/");
-#ifdef DEFAULT_SYSCONFDIR
+#if defined(__EMX__) || defined(OS2)
+ if ((env= getenv("ETC")))
+ errors += add_directory(alloc, env, dirs);
+#elif defined(DEFAULT_SYSCONFDIR)
if (DEFAULT_SYSCONFDIR != "")
- ADD_DIRECTORY(DEFAULT_SYSCONFDIR);
+ errors += add_directory(alloc, DEFAULT_SYSCONFDIR, dirs);
+#endif /* __EMX__ || __OS2__ */
+
#endif
- ADD_COMMON_DIRECTORIES();
- ADD_DIRECTORY("~/");
-}
-static void (*init_default_directories)()= init_default_directories_unix;
+ if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
+ errors += add_directory(alloc, env, dirs);
+
+ /* Placeholder for --defaults-extra-file=<path> */
+ errors += add_directory(alloc, "", dirs);
+#if !defined(__WIN__) && !defined(__NETWARE__) && \
+ !defined(__EMX__) && !defined(OS2)
+ errors += add_directory(alloc, "~/", dirs);
#endif
+
+ return (errors > 0 ? NULL : dirs);
+}