Skip to content

Commit

Permalink
Fix CONC-396.
Browse files Browse the repository at this point in the history
!includedir now includes all .cnf or .ini files, sorted alphabetically,
in the specified directory.
  • Loading branch information
actapia committed Jan 15, 2025
1 parent 3973fb8 commit cbe0b31
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 6 deletions.
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

0 comments on commit cbe0b31

Please sign in to comment.