Skip to content

Commit

Permalink
Fix for MDEV-12965 and MDEV-13100:
Browse files Browse the repository at this point in the history
If no configuration file and no configuration group was specified, Connector/C ddoesn't read any configurationm files.
By default the follwing groups will be read:
- client
- client-server
- client-mariadb

If no configuration file was specified, Connector/C looks up for configuration files in following locations:
- Windows:
  - System directory
  - Windows directory
  - C:\
  - Directoy from which the application was started
  - MYSQL_HOME environment variable
- Unix platforms
  - DEFAULT_SYSCONFIR (if specified)
  or
  - /etc and /etc/mysql
  - MYSQL_HOME environment variable
  - .my.cnf in home directory

Special case: If NULL or empty string will be passed for MYSQL_READ_DEFAULT_GROUP option Connector/C will read the default groups and the group which matches the application name.
  • Loading branch information
9EOR9 committed Jun 25, 2017
1 parent ff4bfdf commit 90fd0cd
Show file tree
Hide file tree
Showing 7 changed files with 378 additions and 60 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDBUG_OFF")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDBUG_OFF")

IF(CMAKE_COMPILER_IS_GNUCC)
ADD_DEFINITIONS(-D_GNU_SOURCE=1)
INCLUDE(CheckCCompilerFlag)
SET(GCC_FLAGS -Wunused -Wno-uninitialized -Wall -Wextra -Wformat-security -Wno-init-self -Wwrite-strings -Wshift-count-overflow -Wdeclaration-after-statement)
FOREACH(GCC_FLAG ${GCC_FLAGS})
Expand Down Expand Up @@ -325,7 +326,7 @@ CONFIGURE_FILE(${CC_SOURCE_DIR}/include/mariadb_version.h.in
INCLUDE_DIRECTORIES(${CC_BINARY_DIR}/include)

IF(WIN32)
SET(SYSTEM_LIBS ws2_32 advapi32 kernel32)
SET(SYSTEM_LIBS ws2_32 advapi32 kernel32 shlwapi)
ELSE()
SET(SYSTEM_LIBS ${LIBPTHREAD} ${LIBDL} ${LIBM})
IF(ICONV_EXTERNAL)
Expand Down
2 changes: 1 addition & 1 deletion include/ma_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -278,4 +278,4 @@
#cmakedefine HAVE_THREADS 1
#cmakedefine SHAREDIR "@SHAREDIR@"
#cmakedefine DEFAULT_CHARSET_HOME "@DEFAULT_CHARSET_HOME@"

#cmakedefine DEFAULT_SYSCONFDIR "@DEFAULT_SYSCONFDIR@"
2 changes: 1 addition & 1 deletion include/ma_global.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define FN_DEVCHAR ':'

#ifndef FN_LIBCHAR
#ifdef __EMX__
#ifdef _WIN32
#define FN_LIBCHAR '\\'
#define FN_ROOTDIR "\\"
#else
Expand Down
205 changes: 149 additions & 56 deletions libmariadb/ma_default.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,90 +27,146 @@

#ifdef _WIN32
#include <io.h>
#include "Shlwapi.h"

static const char *ini_exts[]= {"ini", "cnf", 0};
static const char *ini_dirs[]= {"C:", ".", 0};
static const char *ini_env_dirs[]= {"WINDOWS", "HOMEPATH", 0};
#define ENV_HOME_DIR "HOMEPATH"
#define R_OK 4
#else
#include <unistd.h>
static const char *ini_exts[]= {"cnf", 0};
static const char *ini_dirs[]= {"/etc", "/etc/mysql", ".", 0};
static const char *ini_env_dirs[]= {"HOME", "SYSCONFDIR", 0};
#define ENV_HOME_DIR "HOME"
#endif

extern my_bool _mariadb_set_conf_option(MYSQL *mysql, const char *config_option, const char *config_value);
char **configuration_dirs= NULL;
#define MAX_CONFIG_DIRS 6

char *_mariadb_get_default_file(char *filename, size_t length)
static int add_cfg_dir(char **cfg_dirs, const char *directory)
{
int dirs; int exts;
char *env;
int i;

for (dirs= 0; ini_dirs[dirs]; dirs++)
{
for (exts= 0; ini_exts[exts]; exts++)
{
snprintf(filename, length,
"%s%cmy.%s", ini_dirs[dirs], FN_LIBCHAR, ini_exts[exts]);
if (!access(filename, R_OK))
return filename;
}
for (i=0; i < MAX_CONFIG_DIRS && cfg_dirs[i]; i++);

if (i < MAX_CONFIG_DIRS) {
cfg_dirs[i]= strdup(directory);
return 0;
}
for (dirs= 0; ini_env_dirs[dirs]; dirs++)
return 1;
}

void release_configuration_dirs()
{
if (configuration_dirs)
{
for (exts= 0; ini_exts[exts]; exts++)
{
env= getenv(ini_env_dirs[dirs]);
snprintf(filename, length,
"%s%cmy.%s", env, FN_LIBCHAR, ini_exts[exts]);
if (!access(filename, R_OK))
return filename;
}
int i= 0;
while (configuration_dirs[i])
free(configuration_dirs[i++]);
free(configuration_dirs);
}
}

char **get_default_configuration_dirs()
{
#ifdef _WIN32
char dirname[FN_REFLEN];
#endif
char *env;

configuration_dirs= (char **)calloc(1, (MAX_CONFIG_DIRS + 1) * sizeof(char *));
if (!configuration_dirs)
goto end;

#ifdef _WIN32
/* On Windows operating systems configuration files are stored in
1. System directory
2. Windows directory
3. C:\
*/
if (!GetSystemDirectory(dirname, FN_REFLEN) ||
add_cfg_dir(configuration_dirs, dirname))
goto error;

/* check for .my file in home directoy */
env= getenv(ENV_HOME_DIR);
for (exts= 0; ini_exts[exts]; exts++)
if (!GetWindowsDirectory(dirname, FN_REFLEN) ||
add_cfg_dir(configuration_dirs, dirname))
goto error;

if (add_cfg_dir(configuration_dirs, "C:"))
goto error;

if (GetModuleFileName(NULL, dirname, FN_REFLEN))
{
snprintf(filename, length,
"%s%c.my.%s", env, FN_LIBCHAR, ini_exts[exts]);
if (!access(filename, R_OK))
return filename;
PathRemoveFileSpec(dirname);
if (add_cfg_dir(configuration_dirs, dirname))
goto error;
}
#else
/* on *nix platforms configuration files are stored in
1. SYSCONFDIR (if build happens inside server package, or
-DDEFAULT_SYSCONFDIR was specified
2. /etc
3. /etc/mysql
*/
#ifdef DEFAULT_SYSCONFDIR
if (add_cfg_dir(configuration_dirs, DEFAULT_SYSCONFDIR))
goto error;
#else
if (add_cfg_dir(configuration_dirs, "/etc"))
goto error;
if (add_cfg_dir(configuration_dirs, "/etc/mysql"))
goto error;
#endif
#endif
/* This differs from https://mariadb.com/kb/en/mariadb/configuring-mariadb-with-mycnf/ where MYSQL_HOME is not specified for Windows */
if ((env= getenv("MYSQL_HOME")) &&
add_cfg_dir(configuration_dirs, env))
goto error;
#ifndef _WIN32
if ((env= getenv("HOME")) &&
add_cfg_dir(configuration_dirs, env))
goto error;
#endif
end:
return configuration_dirs;
error:
return NULL;
}

my_bool _mariadb_read_options(MYSQL *mysql, const char *config_file,
const char *group)
extern my_bool _mariadb_set_conf_option(MYSQL *mysql, const char *config_option, const char *config_value);

static my_bool is_group(char *ptr, const char **groups)
{
while (*groups)
{
if (!strcmp(ptr, *groups))
return 1;
groups++;
}
return 0;
}

static my_bool _mariadb_read_options_from_file(MYSQL *mysql,
const char *config_file,
const char *group)
{
uint line=0;
my_bool read_values= 0, found_group= 0, is_escaped= 0, is_quoted= 0;
char buff[4096],*ptr,*end,*value, *key= 0, *optval;
MA_FILE *file= NULL;
char *filename;
uint line=0;
my_bool rc= 1;
my_bool read_values= 0, found_group= 0, is_escaped= 0, is_quoted= 0;
const char *groups[5]= {"client",
"client-server",
"client-mariadb",
group,
NULL};
my_bool (*set_option)(MYSQL *mysql, const char *config_option, const char *config_value);


/* if a plugin registered a hook we will call this hook, otherwise
* default (_mariadb_set_conf_option) will be called */
if (mysql->options.extension && mysql->options.extension->set_option)
set_option= mysql->options.extension->set_option;
else
set_option= _mariadb_set_conf_option;

if (config_file)
filename= strdup(config_file);
else
{
filename= (char *)malloc(FN_REFLEN + 10);
if (!_mariadb_get_default_file(filename, FN_REFLEN + 10))
{
goto err;
}
}

if (!(file = ma_open(filename, "r", NULL)))
if (!(file = ma_open(config_file, "r", NULL)))
goto err;

while (ma_gets(buff,sizeof(buff)-1,file))
Expand All @@ -137,7 +193,7 @@ my_bool _mariadb_read_options(MYSQL *mysql, const char *config_file,
}
for ( ; isspace(end[-1]) ; end--) ; /* Remove end space */
end[0]=0;
read_values= test(strcmp(ptr, group) == 0);
read_values= is_group(ptr, groups);
continue;
}
if (!found_group)
Expand Down Expand Up @@ -224,13 +280,50 @@ my_bool _mariadb_read_options(MYSQL *mysql, const char *config_file,
key= optval= 0;
}
}
if (file)
ma_close(file);
rc= 0;

err:
free(filename);
if (file)
ma_close(file);
return rc;
}


my_bool _mariadb_read_options(MYSQL *mysql,
const char *config_file,
const char *group)
{
int i= 0,
exts,
errors= 0;
char filename[FN_REFLEN + 1];
char *env;

if (config_file)
return _mariadb_read_options_from_file(mysql, config_file, group);

for (i=0; i < MAX_CONFIG_DIRS && configuration_dirs[i]; i++)
{
for (exts= 0; exts < 2; exts++)
{
snprintf(filename, FN_REFLEN,
"%s%cmy.%s", configuration_dirs[i], FN_LIBCHAR, ini_exts[exts]);
if (!access(filename, R_OK))
errors+= _mariadb_read_options_from_file(mysql, filename, group);
}
}
#ifndef _WIN32
/* special case: .my.cnf in Home directory */
if ((env= getenv("HOME")))
{
for (exts= 0; exts < 2; exts++)
{
snprintf(filename, FN_REFLEN,
"%s%c.my.%s", env, FN_LIBCHAR, ini_exts[exts]);
if (!access(filename, R_OK))
errors+= _mariadb_read_options_from_file(mysql, filename, group);
}
}
#endif
return errors;
}
32 changes: 31 additions & 1 deletion libmariadb/mariadb_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
#include <ma_tls.h>
#endif
#include <mysql/client_plugin.h>
#ifdef _WIN32
#include "Shlwapi.h"
#endif

#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15)
#define MA_RPL_VERSION_HACK "5.5.5-"
Expand All @@ -80,6 +83,8 @@ extern ulong net_buffer_length; /* net.c */
static MYSQL_PARAMETERS mariadb_internal_parameters= {&max_allowed_packet, &net_buffer_length, 0};
static my_bool mysql_client_init=0;
static void mysql_close_options(MYSQL *mysql);
extern void release_configuration_dirs();
extern char **get_default_configuration_dirs();
extern my_bool ma_init_done;
extern my_bool mysql_ps_subsystem_initialized;
extern my_bool mysql_handle_local_infile(MYSQL *mysql, const char *filename);
Expand Down Expand Up @@ -1309,7 +1314,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
{
char *hdr = mysql->options.extension->proxy_header;
size_t len = mysql->options.extension->proxy_header_len;
if (ma_pvio_write(pvio, hdr, len) <= 0)
if (ma_pvio_write(pvio, (unsigned char *)hdr, len) <= 0)
{
ma_pvio_close(pvio);
goto error;
Expand Down Expand Up @@ -2655,6 +2660,26 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
OPT_SET_VALUE_STR(&mysql->options, my_cnf_file, (char *)arg1);
break;
case MYSQL_READ_DEFAULT_GROUP:
if (!arg1 || !((char *)arg1)[0])
{
#if defined(__APPLE__) || defined(__FreeBSD__)
const char * appname = getprogname();
#elif defined(_GNU_SOURCE)
const char * appname = program_invocation_short_name;
#elif defined(WIN32)
char appname[FN_REFLEN]= "";

if (GetModuleFileName(NULL, appname, FN_REFLEN))
{
PathStripPath(appname);
PathRemoveExtension(appname);
}
#else
const char * appname = "";
#endif
OPT_SET_VALUE_STR(&mysql->options, my_cnf_group, appname);
break;
}
OPT_SET_VALUE_STR(&mysql->options, my_cnf_group, (char *)arg1);
break;
case MYSQL_SET_CHARSET_DIR:
Expand Down Expand Up @@ -3452,6 +3477,7 @@ static void mysql_once_init()
{
ma_init(); /* Will init threads */
init_client_errs();
get_default_configuration_dirs();
if (mysql_client_plugin_init())
{
#ifdef _WIN32
Expand Down Expand Up @@ -3485,6 +3511,9 @@ static void mysql_once_init()
}
if (!mysql_ps_subsystem_initialized)
mysql_init_ps_subsystem();
#ifdef HAVE_TLS
ma_tls_start(0, 0);
#endif
ignore_sigpipe();
mysql_client_init = 1;
#ifdef _WIN32
Expand Down Expand Up @@ -3522,6 +3551,7 @@ void STDCALL mysql_server_end(void)
if (!mysql_client_init)
return;

release_configuration_dirs();
mysql_client_plugin_deinit();

list_free(pvio_callback, 0);
Expand Down
Loading

0 comments on commit 90fd0cd

Please sign in to comment.