Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cbe0b31

Browse files
committedJan 15, 2025·
Fix CONC-396.
!includedir now includes all .cnf or .ini files, sorted alphabetically, in the specified directory.
1 parent 3973fb8 commit cbe0b31

File tree

2 files changed

+200
-6
lines changed

2 files changed

+200
-6
lines changed
 

‎libmariadb/ma_default.c

+93-2
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,20 @@
2424
#include <mysql.h>
2525
#include <ma_common.h>
2626
#include <mariadb/ma_io.h>
27+
#include <stdlib.h>
2728

2829
#ifdef _WIN32
2930
#include <io.h>
31+
#include <fileapi.h>
32+
#include <string.h>
3033
#include "shlwapi.h"
3134

3235
#define access _access
3336

3437
static const char *ini_exts[]= {"ini", "cnf", 0};
3538
#define R_OK 4
3639
#else
40+
#include <dirent.h>
3741
#include <unistd.h>
3842
static const char *ini_exts[]= {"cnf", 0};
3943
#endif
@@ -152,6 +156,42 @@ static my_bool is_group(char *ptr, const char **groups)
152156
return 0;
153157
}
154158

159+
static my_bool is_config_file(char *path)
160+
{
161+
char *end;
162+
if (access(path, R_OK)) {
163+
return 0;
164+
}
165+
end = path + strlen(path);
166+
for (int exts = 0; ini_exts[exts]; exts++) {
167+
size_t ext_length = strlen(ini_exts[exts]);
168+
char *ext_start = end - ext_length - 1;
169+
170+
if ((ext_start >= path) && (*ext_start == '.')) {
171+
#ifdef _WIN32
172+
if (!_stricmp(ext_start + 1, ini_exts[exts])) {
173+
return 1;
174+
}
175+
#else
176+
if (!strcmp(ext_start + 1, ini_exts[exts])) {
177+
return 1;
178+
}
179+
#endif
180+
}
181+
}
182+
return 0;
183+
}
184+
185+
static int compare_filenames(const void* a, const void* b) {
186+
const char *name_a = *(const char **)a;
187+
const char *name_b = *(const char **)b;
188+
#ifdef _WIN32
189+
return _stricmp(name_a, name_b);
190+
#else
191+
return strcmp(name_a, name_b);
192+
#endif
193+
}
194+
155195
static my_bool _mariadb_read_options_from_file(MYSQL *mysql,
156196
const char *config_file,
157197
const char *group,
@@ -200,8 +240,59 @@ static my_bool _mariadb_read_options_from_file(MYSQL *mysql,
200240
end= strchr(val, 0);
201241
for ( ; isspace(end[-1]) ; end--) ; /* Remove end space */
202242
*end= 0;
203-
if (!strcmp(ptr, "includedir"))
204-
_mariadb_read_options(mysql, (const char *)val, NULL, group, recursion + 1);
243+
if (!strcmp(ptr, "includedir")) {
244+
DYNAMIC_ARRAY filenames;
245+
#ifdef _WIN32
246+
#define MAX_INCLUDE_PATH_LENGTH 4096 + MAX_PATH
247+
HANDLE hFind = NULL;
248+
WIN32_FIND_DATA fdFile;
249+
TCHAR cIncDirFilePattern[MAX_INCLUDE_PATH_LENGTH];
250+
#else
251+
#define MAX_INCLUDE_PATH_LENGTH 4096 + 256
252+
DIR *dir;
253+
struct dirent *ent;
254+
#endif
255+
char inc_config_path[MAX_INCLUDE_PATH_LENGTH];
256+
ma_init_dynamic_array(&filenames, sizeof(char*), 10, 10);
257+
#ifdef _WIN32
258+
for (int exts = 0; ini_exts[exts]; exts++) {
259+
snprintf(cIncDirFilePattern, MAX_INCLUDE_PATH_LENGTH, "%s%c*.%s", val, FN_LIBCHAR, ini_exts[exts]);
260+
if ((hFind = FindFirstFile((const char*)cIncDirFilePattern, &fdFile)) == INVALID_HANDLE_VALUE) {
261+
continue;
262+
}
263+
do {
264+
snprintf(inc_config_path, MAX_INCLUDE_PATH_LENGTH, "%s%c%s", val, FN_LIBCHAR, fdFile.cFileName);
265+
if (!access(inc_config_path, R_OK)) {
266+
char* filename = strdup(fdFile.cFileName);
267+
ma_insert_dynamic(&filenames, (gptr)&filename);
268+
}
269+
} while (FindNextFile(hFind, &fdFile));
270+
FindClose(hFind);
271+
}
272+
#else
273+
if (!(dir = opendir((const char *)val))) {
274+
goto err;
275+
}
276+
while ((ent = readdir(dir))) {
277+
snprintf(inc_config_path, MAX_INCLUDE_PATH_LENGTH, "%s%c%s", val, FN_LIBCHAR, ent->d_name);
278+
if (is_config_file(inc_config_path)) {
279+
/* _mariadb_read_options(mysql, NULL, (const char *)inc_config_path, group, recursion + 1); */
280+
char *filename = strdup(ent->d_name);
281+
ma_insert_dynamic(&filenames, (gptr)&filename);
282+
}
283+
}
284+
closedir(dir);
285+
#endif
286+
qsort(filenames.buffer, filenames.elements, filenames.size_of_element, compare_filenames);
287+
for (uint fi = 0; fi < filenames.elements; fi++) {
288+
char* filename;
289+
ma_get_dynamic(&filenames, (void *)&filename, fi);
290+
snprintf(inc_config_path, MAX_INCLUDE_PATH_LENGTH, "%s%c%s", val, FN_LIBCHAR, filename);
291+
_mariadb_read_options(mysql, NULL, (const char *)inc_config_path, group, recursion + 1);
292+
free(filename);
293+
}
294+
ma_delete_dynamic(&filenames);
295+
}
205296
else if (!strcmp(ptr, "include"))
206297
_mariadb_read_options(mysql, NULL, (const char *)val, group, recursion + 1);
207298
continue;

‎unittest/libmariadb/connection.c

+107-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2626
*/
2727

2828
#include "my_test.h"
29+
#ifdef _WIN32
30+
#include <fileapi.h>
31+
#else
32+
#include <sys/types.h>
33+
#include <sys/stat.h>
34+
#endif
2935

3036
static int test_conc66(MYSQL *my)
3137
{
@@ -1589,6 +1595,102 @@ static int test_conc327(MYSQL *unused __attribute__((unused)))
15891595
}
15901596
#endif
15911597

1598+
static int test_conc396(MYSQL *unused __attribute__((unused)))
1599+
{
1600+
MYSQL *mysql;
1601+
FILE *fp1, *fp2, *fp3;
1602+
char cnf_file1[FN_REFLEN + 10];
1603+
char cnf_dir[FN_REFLEN + 10];
1604+
char cnf_file2[FN_REFLEN + 30];
1605+
char cnf_file3[FN_REFLEN + 30];
1606+
char tmp_dir[FN_REFLEN + 1];
1607+
const char *env = getenv("MYSQL_TMP_DIR");
1608+
fp1 = fp2 = fp3 = NULL;
1609+
1610+
1611+
if (env) {
1612+
strncpy(tmp_dir, env, FN_REFLEN + 1);
1613+
}
1614+
else {
1615+
#ifdef _WIN32
1616+
GetTempPath(FN_REFLEN + 1, tmp_dir);
1617+
#else
1618+
strncpy(tmp_dir, "/tmp", FN_REFLEN + 1);
1619+
#endif
1620+
}
1621+
1622+
snprintf(cnf_file1, FN_REFLEN + 10, "%s%cfoo.cnf", tmp_dir, FN_LIBCHAR);
1623+
snprintf(cnf_dir, FN_REFLEN + 10, "%s%cconf.d", tmp_dir, FN_LIBCHAR);
1624+
snprintf(cnf_file2, FN_REFLEN + 30, "%s%cconfig_a.cnf", cnf_dir, FN_LIBCHAR);
1625+
snprintf(cnf_file3, FN_REFLEN + 30, "%s%cconfig_b.cnf", cnf_dir, FN_LIBCHAR);
1626+
1627+
#ifdef _WIN32
1628+
CreateDirectory(cnf_dir, NULL);
1629+
#else
1630+
mkdir(cnf_dir, 0777);
1631+
#endif
1632+
1633+
mysql = mysql_init(NULL);
1634+
1635+
fp1 = fopen(cnf_file1, "w");
1636+
FAIL_IF(!fp1, "fopen");
1637+
fprintf(fp1, "[client]\n!includedir %s\n", cnf_dir);
1638+
fclose(fp1);
1639+
1640+
/* config_b is alphabetically later, so it should take precendence. */
1641+
fp2 = fopen(cnf_file2, "w");
1642+
FAIL_IF(!fp2, "fopen");
1643+
fprintf(fp2, "[client]\ndefault-character-set = latin2\n");
1644+
fclose(fp2);
1645+
1646+
fp3 = fopen(cnf_file3, "w");
1647+
FAIL_IF(!fp3, "fopen");
1648+
fprintf(fp3, "[client]\ndefault-character-set = utf8mb3\n");
1649+
fclose(fp3);
1650+
1651+
mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, cnf_file1);
1652+
my_test_connect(mysql, hostname, username, password,
1653+
schema, port, socketname, 0, 1);
1654+
1655+
remove(cnf_file1);
1656+
remove(cnf_file2);
1657+
remove(cnf_file3);
1658+
1659+
FAIL_IF(strcmp(mysql_character_set_name(mysql), "utf8mb3"), "expected charset utf8mb3");
1660+
1661+
mysql_close(mysql);
1662+
mysql = mysql_init(NULL);
1663+
1664+
fp1 = fopen(cnf_file1, "w");
1665+
FAIL_IF(!fp1, "fopen");
1666+
fprintf(fp1, "[client]\n!includedir %s\n", cnf_dir);
1667+
fclose(fp1);
1668+
1669+
fp2 = fopen(cnf_file2, "w");
1670+
FAIL_IF(!fp2, "fopen");
1671+
fprintf(fp2, "[client]\ndefault-character-set = utf8mb3\n");
1672+
fclose(fp2);
1673+
1674+
fp3 = fopen(cnf_file3, "w");
1675+
FAIL_IF(!fp3, "fopen");
1676+
fprintf(fp3, "[client]\ndefault-character-set = latin2\n");
1677+
fclose(fp3);
1678+
1679+
mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, cnf_file1);
1680+
my_test_connect(mysql, hostname, username, password,
1681+
schema, port, socketname, 0, 1);
1682+
1683+
remove(cnf_file1);
1684+
remove(cnf_file2);
1685+
remove(cnf_file3);
1686+
1687+
FAIL_IF(strcmp(mysql_character_set_name(mysql), "latin2"), "expected charset latin2");
1688+
1689+
mysql_close(mysql);
1690+
1691+
return OK;
1692+
}
1693+
15921694
static int test_conc332(MYSQL *unused __attribute__((unused)))
15931695
{
15941696
int rc;
@@ -2045,7 +2147,7 @@ static int test_conn_str_1(MYSQL *my __attribute__((unused)))
20452147
if (!(fp= fopen("./conc274.cnf", "w")))
20462148
return FAIL;
20472149

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

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

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

@@ -2140,12 +2242,12 @@ static int test_conc365_reconnect(MYSQL *my)
21402242
if (IS_SKYSQL(hostname))
21412243
{
21422244
snprintf(tmp, sizeof(tmp) - 1,
2143-
"host=127.0.0.1:3300,%s;user=%s;password=%s;port=%d;socket=%s;ssl_enforce=1;tls_fp=%s",
2245+
"host=127.0.0.1:3300,%s;user=%s;password={%s};port=%d;socket=%s;ssl_enforce=1;tls_fp=%s",
21442246
hostname ? hostname : "localhost", username ? username : "", password ? password : "",
21452247
ssl_port, socketname ? socketname : "", fingerprint[0] ? fingerprint : "");
21462248
} else {
21472249
snprintf(tmp, sizeof(tmp) - 1,
2148-
"host=127.0.0.1:3300,%s;user=%s;password=%s;port=%d;socket=%s;tls_fp=%s",
2250+
"host=127.0.0.1:3300,%s;user=%s;password={%s};port=%d;socket=%s;tls_fp=%s",
21492251
hostname ? hostname : "localhost", username ? username : "", password ? password : "",
21502252
port, socketname ? socketname : "", fingerprint[0] ? fingerprint :"");
21512253
}
@@ -2432,6 +2534,7 @@ struct my_tests_st my_tests[] = {
24322534
{"test_conc327", test_conc327, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
24332535
{"test_conc317", test_conc317, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
24342536
#endif
2537+
{"test_conc396", test_conc396, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
24352538
{"test_conc315", test_conc315, TEST_CONNECTION_NEW, 0, NULL, NULL},
24362539
{"test_expired_pw", test_expired_pw, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
24372540
{"test_conc276", test_conc276, TEST_CONNECTION_NONE, 0, NULL, NULL},

0 commit comments

Comments
 (0)