1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

MDEV-26713 UTF8 support on Windows, mysql_upgrade_service preparation

- Tolerate situation, when datadir for service seems invalid/non-existing
prior to upgrade. It could be that my.ini contains legacy ANSI characters
for the data directory. Those can't be read correctly by
mysql_upgrade_service, which uses a different ANSI codepage(UTF8)
.
- schedule upgrade_config_file at later stage, because once we
convert it to UTF-8 (followup patch), this will render config file uselss
with the older version of mariadbd.exe

- Refactor upgrade_conf_file.cc, prepare for UTF-8 conversion.
This commit is contained in:
Vladislav Vaintroub
2021-11-22 13:22:05 +01:00
committed by Sergei Golubchik
parent a4fc41b6b4
commit a296c52627
3 changed files with 124 additions and 58 deletions

View File

@@ -374,13 +374,17 @@ static void change_service_config()
Write datadir to my.ini, after converting backslashes to
unix style slashes.
*/
if (service_properties.datadir[0])
{
strcpy_s(buf, MAX_PATH, service_properties.datadir);
for (i= 0; buf[i]; i++)
{
if (buf[i] == '\\')
buf[i]= '/';
}
WritePrivateProfileString("mysqld", "datadir",buf, service_properties.inifile);
WritePrivateProfileString("mysqld", "datadir", buf,
service_properties.inifile);
}
/*
Remove basedir from defaults file, otherwise the service wont come up in
@@ -465,13 +469,8 @@ int main(int argc, char **argv)
}
}
old_mysqld_exe_exists = (GetFileAttributes(service_properties.mysqld_exe) != INVALID_FILE_ATTRIBUTES);
log("Phase %d/%d: Fixing server config file%s", ++phase, max_phases, my_ini_exists ? "" : "(skipped)");
snprintf(my_ini_bck, sizeof(my_ini_bck), "%s.BCK", service_properties.inifile);
CopyFile(service_properties.inifile, my_ini_bck, FALSE);
upgrade_config_file(service_properties.inifile);
old_mysqld_exe_exists= (GetFileAttributes(service_properties.mysqld_exe) !=
INVALID_FILE_ATTRIBUTES);
bool do_start_stop_server = old_mysqld_exe_exists && initial_service_state != SERVICE_RUNNING;
log("Phase %d/%d: Start and stop server in the old version, to avoid crash recovery %s", ++phase, max_phases,
@@ -526,6 +525,14 @@ int main(int argc, char **argv)
start_duration_ms += 500;
}
}
log("Phase %d/%d: Fixing server config file%s", ++phase, max_phases,
my_ini_exists ? "" : "(skipped)");
snprintf(my_ini_bck, sizeof(my_ini_bck), "%s.BCK",
service_properties.inifile);
CopyFile(service_properties.inifile, my_ini_bck, FALSE);
upgrade_config_file(service_properties.inifile);
/*
Start mysqld.exe as non-service skipping privileges (so we do not
care about the password). But disable networking and enable pipe

View File

@@ -158,16 +158,19 @@ static int cmp_strings(const void* a, const void *b)
return strcmp((const char *)a, *(const char **)b);
}
/**
Convert file from a previous version, by removing
*/
int upgrade_config_file(const char *myini_path)
{
#define MY_INI_SECTION_SIZE 32 * 1024 + 3
static char section_data[MY_INI_SECTION_SIZE];
for (const char *section_name : { "mysqld","server","mariadb" })
int fix_section(const char *myini_path, const char *section_name,
bool is_server)
{
DWORD size = GetPrivateProfileSection(section_name, section_data, MY_INI_SECTION_SIZE, myini_path);
if (!is_server)
return 0;
static char section_data[MY_INI_SECTION_SIZE];
DWORD size= GetPrivateProfileSection(section_name, section_data,
MY_INI_SECTION_SIZE, myini_path);
if (size == MY_INI_SECTION_SIZE - 2)
{
return -1;
@@ -176,13 +179,19 @@ int upgrade_config_file(const char *myini_path)
for (char *keyval= section_data; *keyval; keyval += strlen(keyval)+1)
{
char varname[256];
char *value;
char *key_end= strchr(keyval, '=');
if (!key_end)
key_end= keyval + strlen(keyval);
if (key_end - keyval > sizeof(varname))
continue;
// copy and normalize (convert dash to underscore) to variable names
value= key_end + 1;
// Check if variable should be removed from config.
// First, copy and normalize (convert dash to underscore) to variable
// names
for (char *p= keyval, *q= varname;; p++, q++)
{
if (p == key_end)
@@ -203,6 +212,49 @@ int upgrade_config_file(const char *myini_path)
WritePrivateProfileString(section_name, keyval, 0, myini_path);
}
}
return 0;
}
static bool is_mariadb_section(const char *name, bool *is_server)
{
if (strncmp(name, "mysql", 5)
&& strncmp(name, "mariadb", 7)
&& strcmp(name, "client")
&& strcmp(name, "client-server")
&& strcmp(name, "server"))
{
return false;
}
for (const char *section_name : {"mysqld", "server", "mariadb"})
if (*is_server= !strcmp(section_name, name))
break;
return *is_server;
}
/**
Convert file from a previous version, by removing obsolete variables
Also, fix values to be UTF8, if MariaDB is running in utf8 mode
*/
int upgrade_config_file(const char *myini_path)
{
static char all_sections[MY_INI_SECTION_SIZE];
int sz= GetPrivateProfileSectionNamesA(all_sections, MY_INI_SECTION_SIZE,
myini_path);
if (!sz)
return 0;
if (sz > MY_INI_SECTION_SIZE - 2)
{
fprintf(stderr, "Too many sections in config file\n");
return -1;
}
for (char *section= all_sections; *section; section+= strlen(section) + 1)
{
bool is_server_section;
if (is_mariadb_section(section, &is_server_section))
fix_section(myini_path, section, is_server_section);
}
return 0;
}

View File

@@ -134,6 +134,20 @@ static void get_datadir_from_ini(const char *ini, char *service_name, char *data
}
static int fix_and_check_datadir(mysqld_service_properties *props)
{
normalize_path(props->datadir, MAX_PATH);
/* Check if datadir really exists */
if (GetFileAttributes(props->datadir) != INVALID_FILE_ATTRIBUTES)
return 0;
/*
It is possible, that datadir contains some unconvertable character.
We just pretend not to know what's the data directory
*/
props->datadir[0]= 0;
return 0;
}
/*
Retrieve some properties from windows mysqld service binary path.
We're interested in ini file location and datadir, and also in version of
@@ -284,16 +298,9 @@ int get_mysql_service_properties(const wchar_t *bin_path,
}
}
if (props->datadir[0])
if (props->datadir[0] == 0 || fix_and_check_datadir(props))
{
normalize_path(props->datadir, MAX_PATH);
/* Check if datadir really exists */
if (GetFileAttributes(props->datadir) == INVALID_FILE_ATTRIBUTES)
goto end;
}
else
{
/* There is no datadir in ini file, bail out.*/
/* There is no datadir in ini file, or non-existing dir, bail out.*/
goto end;
}