List:Commits« Previous MessageNext Message »
From:tim Date:March 14 2008 9:35pm
Subject:bk commit into 5.0 tree (tsmith:1.2576) BUG#20748
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of tsmith.  When tsmith does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-03-14 14:35:17-06:00, tsmith@stripped +1 -0
  Bug #20748: Configuration files should not be read more than once
  
  Normalize directory names before adding them to default_directories.

  mysys/default.c@stripped, 2008-03-14 14:35:16-06:00, tsmith@stripped +129 -155
    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.
    

diff -Nrup a/mysys/default.c b/mysys/default.c
--- a/mysys/default.c	2007-11-16 14:56:35 -07:00
+++ b/mysys/default.c	2008-03-14 14:35:16 -06:00
@@ -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(
 					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,
   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 *
   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_fil
 #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_direct
 }
 
 
-/**
-  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;
 
-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);
+}
Thread
bk commit into 5.0 tree (tsmith:1.2576) BUG#20748tim14 Mar 2008
  • Re: bk commit into 5.0 tree (tsmith:1.2576) BUG#20748Sergei Golubchik18 Jun 2008