Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 93 additions & 2 deletions libmariadb/ma_default.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,20 @@
#include <mysql.h>
#include <ma_common.h>
#include <mariadb/ma_io.h>
#include <stdlib.h>

#ifdef _WIN32
#include <io.h>
#include <fileapi.h>
#include <string.h>
#include "shlwapi.h"

#define access _access

static const char *ini_exts[]= {"ini", "cnf", 0};
#define R_OK 4
#else
#include <dirent.h>
#include <unistd.h>
static const char *ini_exts[]= {"cnf", 0};
#endif
Expand Down Expand Up @@ -152,6 +156,42 @@ static my_bool is_group(char *ptr, const char **groups)
return 0;
}

static my_bool is_config_file(char *path)
{
char *end;
if (access(path, R_OK)) {
return 0;
}
end = path + strlen(path);
for (int exts = 0; ini_exts[exts]; exts++) {
size_t ext_length = strlen(ini_exts[exts]);
char *ext_start = end - ext_length - 1;

if ((ext_start >= path) && (*ext_start == '.')) {
#ifdef _WIN32
if (!_stricmp(ext_start + 1, ini_exts[exts])) {
return 1;
}
#else
if (!strcmp(ext_start + 1, ini_exts[exts])) {
return 1;
}
#endif
}
}
return 0;
}

static int compare_filenames(const void* a, const void* b) {
const char *name_a = *(const char **)a;
const char *name_b = *(const char **)b;
#ifdef _WIN32
return _stricmp(name_a, name_b);
#else
return strcmp(name_a, name_b);
#endif
}

static my_bool _mariadb_read_options_from_file(MYSQL *mysql,
const char *config_file,
const char *group,
Expand Down Expand Up @@ -200,8 +240,59 @@ static my_bool _mariadb_read_options_from_file(MYSQL *mysql,
end= strchr(val, 0);
for ( ; isspace(end[-1]) ; end--) ; /* Remove end space */
*end= 0;
if (!strcmp(ptr, "includedir"))
_mariadb_read_options(mysql, (const char *)val, NULL, group, recursion + 1);
if (!strcmp(ptr, "includedir")) {
DYNAMIC_ARRAY filenames;
#ifdef _WIN32
#define MAX_INCLUDE_PATH_LENGTH 4096 + MAX_PATH
HANDLE hFind = NULL;
WIN32_FIND_DATA fdFile;
TCHAR cIncDirFilePattern[MAX_INCLUDE_PATH_LENGTH];
#else
#define MAX_INCLUDE_PATH_LENGTH 4096 + 256
DIR *dir;
struct dirent *ent;
#endif
char inc_config_path[MAX_INCLUDE_PATH_LENGTH];
ma_init_dynamic_array(&filenames, sizeof(char*), 10, 10);
#ifdef _WIN32
for (int exts = 0; ini_exts[exts]; exts++) {
snprintf(cIncDirFilePattern, MAX_INCLUDE_PATH_LENGTH, "%s%c*.%s", val, FN_LIBCHAR, ini_exts[exts]);
if ((hFind = FindFirstFile((const char*)cIncDirFilePattern, &fdFile)) == INVALID_HANDLE_VALUE) {
continue;
}
do {
snprintf(inc_config_path, MAX_INCLUDE_PATH_LENGTH, "%s%c%s", val, FN_LIBCHAR, fdFile.cFileName);
if (!access(inc_config_path, R_OK)) {
char* filename = strdup(fdFile.cFileName);
ma_insert_dynamic(&filenames, (gptr)&filename);
}
} while (FindNextFile(hFind, &fdFile));
FindClose(hFind);
}
#else
if (!(dir = opendir((const char *)val))) {
goto err;
}
while ((ent = readdir(dir))) {
snprintf(inc_config_path, MAX_INCLUDE_PATH_LENGTH, "%s%c%s", val, FN_LIBCHAR, ent->d_name);
if (is_config_file(inc_config_path)) {
/* _mariadb_read_options(mysql, NULL, (const char *)inc_config_path, group, recursion + 1); */
char *filename = strdup(ent->d_name);
ma_insert_dynamic(&filenames, (gptr)&filename);
}
}
closedir(dir);
#endif
qsort(filenames.buffer, filenames.elements, filenames.size_of_element, compare_filenames);
for (uint fi = 0; fi < filenames.elements; fi++) {
char* filename;
ma_get_dynamic(&filenames, (void *)&filename, fi);
snprintf(inc_config_path, MAX_INCLUDE_PATH_LENGTH, "%s%c%s", val, FN_LIBCHAR, filename);
_mariadb_read_options(mysql, NULL, (const char *)inc_config_path, group, recursion + 1);
free(filename);
}
ma_delete_dynamic(&filenames);
}
else if (!strcmp(ptr, "include"))
_mariadb_read_options(mysql, NULL, (const char *)val, group, recursion + 1);
continue;
Expand Down
111 changes: 107 additions & 4 deletions unittest/libmariadb/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/

#include "my_test.h"
#ifdef _WIN32
#include <fileapi.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif

static int test_conc66(MYSQL *my)
{
Expand Down Expand Up @@ -1589,6 +1595,102 @@ static int test_conc327(MYSQL *unused __attribute__((unused)))
}
#endif

static int test_conc396(MYSQL *unused __attribute__((unused)))
{
MYSQL *mysql;
FILE *fp1, *fp2, *fp3;
char cnf_file1[FN_REFLEN + 10];
char cnf_dir[FN_REFLEN + 10];
char cnf_file2[FN_REFLEN + 30];
char cnf_file3[FN_REFLEN + 30];
char tmp_dir[FN_REFLEN + 1];
const char *env = getenv("MYSQL_TMP_DIR");
fp1 = fp2 = fp3 = NULL;


if (env) {
strncpy(tmp_dir, env, FN_REFLEN + 1);
}
else {
#ifdef _WIN32
GetTempPath(FN_REFLEN + 1, tmp_dir);
#else
strncpy(tmp_dir, "/tmp", FN_REFLEN + 1);
#endif
}

snprintf(cnf_file1, FN_REFLEN + 10, "%s%cfoo.cnf", tmp_dir, FN_LIBCHAR);
snprintf(cnf_dir, FN_REFLEN + 10, "%s%cconf.d", tmp_dir, FN_LIBCHAR);
snprintf(cnf_file2, FN_REFLEN + 30, "%s%cconfig_a.cnf", cnf_dir, FN_LIBCHAR);
snprintf(cnf_file3, FN_REFLEN + 30, "%s%cconfig_b.cnf", cnf_dir, FN_LIBCHAR);

#ifdef _WIN32
CreateDirectory(cnf_dir, NULL);
#else
mkdir(cnf_dir, 0777);
#endif

mysql = mysql_init(NULL);

fp1 = fopen(cnf_file1, "w");
FAIL_IF(!fp1, "fopen");
fprintf(fp1, "[client]\n!includedir %s\n", cnf_dir);
fclose(fp1);

/* config_b is alphabetically later, so it should take precendence. */
fp2 = fopen(cnf_file2, "w");
FAIL_IF(!fp2, "fopen");
fprintf(fp2, "[client]\ndefault-character-set = latin2\n");
fclose(fp2);

fp3 = fopen(cnf_file3, "w");
FAIL_IF(!fp3, "fopen");
fprintf(fp3, "[client]\ndefault-character-set = utf8mb3\n");
fclose(fp3);

mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, cnf_file1);
my_test_connect(mysql, hostname, username, password,
schema, port, socketname, 0, 1);

remove(cnf_file1);
remove(cnf_file2);
remove(cnf_file3);

FAIL_IF(strcmp(mysql_character_set_name(mysql), "utf8mb3"), "expected charset utf8mb3");

mysql_close(mysql);
mysql = mysql_init(NULL);

fp1 = fopen(cnf_file1, "w");
FAIL_IF(!fp1, "fopen");
fprintf(fp1, "[client]\n!includedir %s\n", cnf_dir);
fclose(fp1);

fp2 = fopen(cnf_file2, "w");
FAIL_IF(!fp2, "fopen");
fprintf(fp2, "[client]\ndefault-character-set = utf8mb3\n");
fclose(fp2);

fp3 = fopen(cnf_file3, "w");
FAIL_IF(!fp3, "fopen");
fprintf(fp3, "[client]\ndefault-character-set = latin2\n");
fclose(fp3);

mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, cnf_file1);
my_test_connect(mysql, hostname, username, password,
schema, port, socketname, 0, 1);

remove(cnf_file1);
remove(cnf_file2);
remove(cnf_file3);

FAIL_IF(strcmp(mysql_character_set_name(mysql), "latin2"), "expected charset latin2");

mysql_close(mysql);

return OK;
}

static int test_conc332(MYSQL *unused __attribute__((unused)))
{
int rc;
Expand Down Expand Up @@ -2045,7 +2147,7 @@ static int test_conn_str_1(MYSQL *my __attribute__((unused)))
if (!(fp= fopen("./conc274.cnf", "w")))
return FAIL;

sprintf(conn_str, "connection=host=%s;user=%s;password=%s;port=%d;ssl_enforce=1;socket=%s",
sprintf(conn_str, "connection=host=%s;user=%s;password={%s};port=%d;ssl_enforce=1;socket=%s",
hostname ? hostname : "localhost", username ? username : "",
password ? password : "", ssl_port, socketname ? socketname : "");

Expand Down Expand Up @@ -2084,7 +2186,7 @@ static int test_conc365(MYSQL *my __attribute__((unused)))
char tmp[1024];

snprintf(tmp, sizeof(tmp) - 1,
"host=127.0.0.1:3300,%s;user=%s;password=%s;port=%d;socket=%s;tls_fp=%s",
"host=127.0.0.1:3300,%s;user=%s;password={%s};port=%d;socket=%s;tls_fp=%s",
hostname ? hostname : "localhost", username ? username : "", password ? password : "",
port, socketname ? socketname : "", fingerprint[0] ? fingerprint : "");

Expand Down Expand Up @@ -2140,12 +2242,12 @@ static int test_conc365_reconnect(MYSQL *my)
if (IS_SKYSQL(hostname))
{
snprintf(tmp, sizeof(tmp) - 1,
"host=127.0.0.1:3300,%s;user=%s;password=%s;port=%d;socket=%s;ssl_enforce=1;tls_fp=%s",
"host=127.0.0.1:3300,%s;user=%s;password={%s};port=%d;socket=%s;ssl_enforce=1;tls_fp=%s",
hostname ? hostname : "localhost", username ? username : "", password ? password : "",
ssl_port, socketname ? socketname : "", fingerprint[0] ? fingerprint : "");
} else {
snprintf(tmp, sizeof(tmp) - 1,
"host=127.0.0.1:3300,%s;user=%s;password=%s;port=%d;socket=%s;tls_fp=%s",
"host=127.0.0.1:3300,%s;user=%s;password={%s};port=%d;socket=%s;tls_fp=%s",
hostname ? hostname : "localhost", username ? username : "", password ? password : "",
port, socketname ? socketname : "", fingerprint[0] ? fingerprint :"");
}
Expand Down Expand Up @@ -2432,6 +2534,7 @@ struct my_tests_st my_tests[] = {
{"test_conc327", test_conc327, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_conc317", test_conc317, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
#endif
{"test_conc396", test_conc396, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_conc315", test_conc315, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_expired_pw", test_expired_pw, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_conc276", test_conc276, TEST_CONNECTION_NONE, 0, NULL, NULL},
Expand Down