mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Revert "MDEV-26713 Windows - improve utf8 support for command line tools"
This reverts commit several commits pushed by mistake.
This commit is contained in:
126
client/mysql.cc
126
client/mysql.cc
@ -88,7 +88,9 @@ extern "C" {
|
|||||||
#endif /* defined(HAVE_CURSES_H) && defined(HAVE_TERM_H) */
|
#endif /* defined(HAVE_CURSES_H) && defined(HAVE_TERM_H) */
|
||||||
|
|
||||||
#undef bcmp // Fix problem with new readline
|
#undef bcmp // Fix problem with new readline
|
||||||
#if !defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
#include <conio.h>
|
||||||
|
#else
|
||||||
# ifdef __APPLE__
|
# ifdef __APPLE__
|
||||||
# include <editline/readline.h>
|
# include <editline/readline.h>
|
||||||
# else
|
# else
|
||||||
@ -102,101 +104,6 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
/*
|
|
||||||
Set console mode for the whole duration of the client session.
|
|
||||||
|
|
||||||
We need for input
|
|
||||||
- line input (i.e read lines from console)
|
|
||||||
- echo typed characters
|
|
||||||
- "cooked" mode, i.e we do not want to handle all keystrokes,
|
|
||||||
like DEL etc ourselves, yet. We might want handle keystrokes
|
|
||||||
in the future, to implement tab completion, and better
|
|
||||||
(multiline) history.
|
|
||||||
|
|
||||||
Disable VT escapes for the output.We do not know what kind of escapes SELECT would return.
|
|
||||||
*/
|
|
||||||
struct Console_mode
|
|
||||||
{
|
|
||||||
HANDLE in= GetStdHandle(STD_INPUT_HANDLE);
|
|
||||||
HANDLE out= GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
DWORD mode_in=0;
|
|
||||||
DWORD mode_out=0;
|
|
||||||
|
|
||||||
enum {STDIN_CHANGED = 1, STDOUT_CHANGED = 2};
|
|
||||||
int changes=0;
|
|
||||||
|
|
||||||
Console_mode()
|
|
||||||
{
|
|
||||||
if (in && in != INVALID_HANDLE_VALUE && GetConsoleMode(in, &mode_in))
|
|
||||||
{
|
|
||||||
SetConsoleMode(in, ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT);
|
|
||||||
changes |= STDIN_CHANGED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out && out != INVALID_HANDLE_VALUE && GetConsoleMode(out, &mode_out))
|
|
||||||
{
|
|
||||||
#ifdef ENABLE_VIRTUAL_TERMINAL_INPUT
|
|
||||||
SetConsoleMode(out, mode_out & ~ENABLE_VIRTUAL_TERMINAL_INPUT);
|
|
||||||
changes |= STDOUT_CHANGED;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~Console_mode()
|
|
||||||
{
|
|
||||||
if (changes & STDIN_CHANGED)
|
|
||||||
SetConsoleMode(in, mode_in);
|
|
||||||
|
|
||||||
if(changes & STDOUT_CHANGED)
|
|
||||||
SetConsoleMode(out, mode_out);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static Console_mode my_conmode;
|
|
||||||
|
|
||||||
#define MAX_CGETS_LINE_LEN 65535
|
|
||||||
/** Read line from console in ANSI codepage, chomp EOL*/
|
|
||||||
static char *win_readline()
|
|
||||||
{
|
|
||||||
static wchar_t wstrbuf[MAX_CGETS_LINE_LEN];
|
|
||||||
static char strbuf[MAX_CGETS_LINE_LEN*2];
|
|
||||||
|
|
||||||
DWORD nchars= 0;
|
|
||||||
SetLastError(0);
|
|
||||||
if (!ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), wstrbuf, MAX_CGETS_LINE_LEN-1,
|
|
||||||
&nchars, NULL))
|
|
||||||
goto err;
|
|
||||||
if (nchars == 0 && GetLastError() == ERROR_OPERATION_ABORTED)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
while (nchars > 0)
|
|
||||||
{
|
|
||||||
if (wstrbuf[nchars - 1] != '\n' && wstrbuf[nchars - 1] != '\r')
|
|
||||||
break;
|
|
||||||
wstrbuf[--nchars]= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
wstrbuf[nchars]= 0;
|
|
||||||
if (nchars > 0)
|
|
||||||
{
|
|
||||||
int len = WideCharToMultiByte(GetConsoleCP(), 0, wstrbuf, nchars + 1,
|
|
||||||
strbuf, sizeof(strbuf),NULL, NULL);
|
|
||||||
if (len < 1)
|
|
||||||
strbuf[0]= 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strbuf[0]= 0;
|
|
||||||
}
|
|
||||||
return strbuf;
|
|
||||||
err:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_VIDATTR
|
#ifdef HAVE_VIDATTR
|
||||||
static int have_curses= 0;
|
static int have_curses= 0;
|
||||||
static void my_vidattr(chtype attrs)
|
static void my_vidattr(chtype attrs)
|
||||||
@ -1812,10 +1719,8 @@ static void usage(int version)
|
|||||||
my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE,
|
my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE,
|
||||||
readline, rl_library_version);
|
readline, rl_library_version);
|
||||||
#else
|
#else
|
||||||
printf("%s Ver %s Distrib %s, for %s (%s), source revision %s"
|
printf("%s Ver %s Distrib %s, for %s (%s), source revision %s\n", my_progname, VER,
|
||||||
IF_WIN(", codepage %u",) "\n", my_progname, VER,
|
MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE,SOURCE_REVISION);
|
||||||
MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE,SOURCE_REVISION,
|
|
||||||
IF_WIN(GetConsoleCP(),));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (version)
|
if (version)
|
||||||
@ -2210,7 +2115,26 @@ static int read_and_execute(bool interactive)
|
|||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
tee_fputs(prompt, stdout);
|
tee_fputs(prompt, stdout);
|
||||||
line= win_readline();
|
if (!tmpbuf.is_alloced())
|
||||||
|
tmpbuf.alloc(65535);
|
||||||
|
tmpbuf.length(0);
|
||||||
|
buffer.length(0);
|
||||||
|
size_t clen;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
line= my_cgets((char*)tmpbuf.ptr(), tmpbuf.alloced_length()-1, &clen);
|
||||||
|
buffer.append(line, clen);
|
||||||
|
/*
|
||||||
|
if we got buffer fully filled than there is a chance that
|
||||||
|
something else is still in console input buffer
|
||||||
|
*/
|
||||||
|
} while (tmpbuf.alloced_length() <= clen);
|
||||||
|
/*
|
||||||
|
An empty line is returned from my_cgets when there's error reading :
|
||||||
|
Ctrl-c for example
|
||||||
|
*/
|
||||||
|
if (line)
|
||||||
|
line= buffer.c_ptr();
|
||||||
#else
|
#else
|
||||||
if (opt_outfile)
|
if (opt_outfile)
|
||||||
fputs(prompt, OUTFILE);
|
fputs(prompt, OUTFILE);
|
||||||
|
@ -60,8 +60,8 @@ ENDIF()
|
|||||||
|
|
||||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
|
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
|
||||||
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0A00)
|
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0A00)
|
||||||
# We do not want the windows.h , or winsvc.h macros min/max
|
# We do not want the windows.h macros min/max
|
||||||
ADD_DEFINITIONS(-DNOMINMAX -DNOSERVICE)
|
ADD_DEFINITIONS(-DNOMINMAX)
|
||||||
# Speed up build process excluding unused header files
|
# Speed up build process excluding unused header files
|
||||||
ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
|
ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
|
||||||
|
|
||||||
|
@ -19,9 +19,4 @@
|
|||||||
|
|
||||||
</application>
|
</application>
|
||||||
</compatibility>
|
</compatibility>
|
||||||
<application>
|
|
||||||
<windowsSettings>
|
|
||||||
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
|
|
||||||
</windowsSettings>
|
|
||||||
</application>
|
|
||||||
</asmv1:assembly>
|
</asmv1:assembly>
|
||||||
|
@ -29,14 +29,6 @@
|
|||||||
#pragma GCC poison __WIN__
|
#pragma GCC poison __WIN__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
/*
|
|
||||||
Following functions have bugs, when used with UTF-8 active codepage.
|
|
||||||
#include <winservice.h> will use the non-buggy wrappers
|
|
||||||
*/
|
|
||||||
#pragma deprecated("CreateServiceA", "OpenServiceA", "ChangeServiceConfigA")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
InnoDB depends on some MySQL internals which other plugins should not
|
InnoDB depends on some MySQL internals which other plugins should not
|
||||||
need. This is because of InnoDB's foreign key support, "safe" binlog
|
need. This is because of InnoDB's foreign key support, "safe" binlog
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
--source include/windows.inc
|
--source include/windows.inc
|
||||||
--exec set MARIADB_DISABLE_UTF8_CONSOLE=1 && chcp 1257 > NUL && $MYSQL --default-character-set=auto -e "select @@character_set_client"
|
--exec chcp 1257 > NUL && $MYSQL --default-character-set=auto -e "select @@character_set_client"
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
@@character_set_client
|
|
||||||
utf8mb4
|
|
@ -1,2 +0,0 @@
|
|||||||
--source include/windows.inc
|
|
||||||
--exec $MYSQL --default-character-set=auto -e "select @@character_set_client"
|
|
@ -1,3 +1,5 @@
|
|||||||
|
# UTF8 parameters to mysql client do not work on Windows
|
||||||
|
--source include/not_windows.inc
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
|
||||||
#
|
#
|
@ -87,23 +87,6 @@ sub skip_combinations {
|
|||||||
$skip{'main/ssl_verify_ip.test'} = 'x509v3 support required'
|
$skip{'main/ssl_verify_ip.test'} = 'x509v3 support required'
|
||||||
unless $openssl_ver ge "1.0.2";
|
unless $openssl_ver ge "1.0.2";
|
||||||
|
|
||||||
sub utf8_command_line_ok() {
|
|
||||||
if (IS_WINDOWS) {
|
|
||||||
# Can use UTF8 on command line since Windows 10 1903 (10.0.18362)
|
|
||||||
my($os_name, $os_major, $os_minor, $os_build, $os_id) = Win32::GetOSVersion();
|
|
||||||
if($os_major lt 10){
|
|
||||||
return 0;
|
|
||||||
} elsif($os_major gt 10 or $os_minor gt 0 or $os_build ge 18362) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$skip{'main/charset_client_win_utf8mb4.test'} =
|
|
||||||
$skip{'main/grant_utf8_cli.test'} = 'No utf8 command line support'
|
|
||||||
unless utf8_command_line_ok();
|
|
||||||
|
|
||||||
%skip;
|
%skip;
|
||||||
}
|
}
|
||||||
|
@ -1393,7 +1393,7 @@ static const MY_CSET_OS_NAME charsets[] =
|
|||||||
#ifdef UNCOMMENT_THIS_WHEN_WL_WL_4024_IS_DONE
|
#ifdef UNCOMMENT_THIS_WHEN_WL_WL_4024_IS_DONE
|
||||||
{"cp54936", "gb18030", my_cs_exact},
|
{"cp54936", "gb18030", my_cs_exact},
|
||||||
#endif
|
#endif
|
||||||
{"cp65001", "utf8mb4", my_cs_exact},
|
{"cp65001", "utf8", my_cs_exact},
|
||||||
|
|
||||||
#else /* not Windows */
|
#else /* not Windows */
|
||||||
|
|
||||||
|
@ -62,40 +62,34 @@
|
|||||||
|
|
||||||
char *get_tty_password(const char *opt_message)
|
char *get_tty_password(const char *opt_message)
|
||||||
{
|
{
|
||||||
wchar_t wbuf[80];
|
char to[80];
|
||||||
char to[80*3]; /* there is at most 3 bytes per wchar, in any codepage */
|
char *pos=to,*end=to+sizeof(to)-1;
|
||||||
wchar_t *pos=wbuf,*end=wbuf + array_elements(wbuf)-1;
|
|
||||||
DBUG_ENTER("get_tty_password");
|
DBUG_ENTER("get_tty_password");
|
||||||
_cputs(opt_message ? opt_message : "Enter password: ");
|
_cputs(opt_message ? opt_message : "Enter password: ");
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int wc;
|
char tmp;
|
||||||
wc=_getwch();
|
tmp=_getch();
|
||||||
if (wc == '\b' || wc == 127)
|
if (tmp == '\b' || (int) tmp == 127)
|
||||||
{
|
{
|
||||||
if (pos != wbuf)
|
if (pos != to)
|
||||||
{
|
{
|
||||||
_cputs("\b \b");
|
_cputs("\b \b");
|
||||||
pos--;
|
pos--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (wc == '\n' || wc == '\r' || wc == 3 || pos == end)
|
if (tmp == '\n' || tmp == '\r' || tmp == 3)
|
||||||
break;
|
break;
|
||||||
if (iswcntrl(wc))
|
if (iscntrl(tmp) || pos == end)
|
||||||
continue;
|
continue;
|
||||||
|
_cputs("*");
|
||||||
/* Do not print '*' for half-unicode char(high surrogate)*/
|
*(pos++) = tmp;
|
||||||
if (wc < 0xD800 || wc > 0xDBFF)
|
|
||||||
{
|
|
||||||
_cputs("*");
|
|
||||||
}
|
|
||||||
*(pos++)= (wchar_t)wc;
|
|
||||||
}
|
}
|
||||||
|
while (pos != to && isspace(pos[-1]) == ' ')
|
||||||
|
pos--; /* Allow dummy space at end */
|
||||||
*pos=0;
|
*pos=0;
|
||||||
_cputs("\n");
|
_cputs("\n");
|
||||||
if (!WideCharToMultiByte(GetConsoleCP(), 0 , wbuf , -1 , to, sizeof(to), NULL, NULL))
|
|
||||||
to[0]=0;
|
|
||||||
DBUG_RETURN(my_strdup(PSI_INSTRUMENT_ME, to,MYF(MY_FAE)));
|
DBUG_RETURN(my_strdup(PSI_INSTRUMENT_ME, to,MYF(MY_FAE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ static double getopt_double(char *arg, const struct my_option *optp, int *err);
|
|||||||
static void init_variables(const struct my_option *, init_func_p);
|
static void init_variables(const struct my_option *, init_func_p);
|
||||||
static void init_one_value(const struct my_option *, void *, longlong);
|
static void init_one_value(const struct my_option *, void *, longlong);
|
||||||
static void fini_one_value(const struct my_option *, void *, longlong);
|
static void fini_one_value(const struct my_option *, void *, longlong);
|
||||||
static int setval(const struct my_option *, void *, char *, my_bool, const char *);
|
static int setval(const struct my_option *, void *, char *, my_bool);
|
||||||
static char *check_struct_option(char *cur_arg, char *key_name);
|
static char *check_struct_option(char *cur_arg, char *key_name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -133,48 +133,6 @@ double getopt_ulonglong2double(ulonglong v)
|
|||||||
return u.dbl;
|
return u.dbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
/**
|
|
||||||
|
|
||||||
On Windows, if program is running in UTF8 mode, but some arguments are not UTF8.
|
|
||||||
|
|
||||||
This will mostly likely be a sign of old "ANSI" my.ini, and it is likely that
|
|
||||||
something will go wrong, e.g file access error.
|
|
||||||
*/
|
|
||||||
static void validate_value(const char *key, const char *value,
|
|
||||||
const char *filename)
|
|
||||||
{
|
|
||||||
MY_STRCOPY_STATUS status;
|
|
||||||
const struct charset_info_st *cs= &my_charset_utf8mb4_bin;
|
|
||||||
size_t len;
|
|
||||||
if (GetACP() != CP_UTF8)
|
|
||||||
return;
|
|
||||||
len= strlen(value);
|
|
||||||
if (!len)
|
|
||||||
return;
|
|
||||||
cs->cset->well_formed_char_length(cs, value, value + len, len, &status);
|
|
||||||
if (!status.m_well_formed_error_pos)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (filename && *filename)
|
|
||||||
{
|
|
||||||
my_getopt_error_reporter(WARNING_LEVEL,
|
|
||||||
"%s: invalid (non-UTF8) characters found for option '%s'"
|
|
||||||
" in file '%s'",
|
|
||||||
my_progname, key, filename);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(0);
|
|
||||||
my_getopt_error_reporter(
|
|
||||||
WARNING_LEVEL, "%s: invalid (non-UTF8) characters for option %s",
|
|
||||||
my_progname, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define validate_value(key, value, filename) (void)filename
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Handle command line options.
|
Handle command line options.
|
||||||
Sort options.
|
Sort options.
|
||||||
@ -606,7 +564,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((error= setval(optp, optp->value, argument,
|
if ((error= setval(optp, optp->value, argument,
|
||||||
set_maximum_value,filename)))
|
set_maximum_value)))
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
if (get_one_option(optp, argument, filename))
|
if (get_one_option(optp, argument, filename))
|
||||||
DBUG_RETURN(EXIT_UNSPECIFIED_ERROR);
|
DBUG_RETURN(EXIT_UNSPECIFIED_ERROR);
|
||||||
@ -652,7 +610,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((!option_is_autoset) &&
|
if ((!option_is_autoset) &&
|
||||||
((error= setval(optp, value, argument, set_maximum_value,filename))) &&
|
((error= setval(optp, value, argument, set_maximum_value))) &&
|
||||||
!option_is_loose)
|
!option_is_loose)
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
if (get_one_option(optp, argument, filename))
|
if (get_one_option(optp, argument, filename))
|
||||||
@ -753,7 +711,7 @@ static my_bool get_bool_argument(const struct my_option *opts,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int setval(const struct my_option *opts, void *value, char *argument,
|
static int setval(const struct my_option *opts, void *value, char *argument,
|
||||||
my_bool set_maximum_value, const char *option_file)
|
my_bool set_maximum_value)
|
||||||
{
|
{
|
||||||
int err= 0, res= 0;
|
int err= 0, res= 0;
|
||||||
DBUG_ENTER("setval");
|
DBUG_ENTER("setval");
|
||||||
@ -900,7 +858,6 @@ static int setval(const struct my_option *opts, void *value, char *argument,
|
|||||||
goto ret;
|
goto ret;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
validate_value(opts->name, argument, option_file);
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
ret:
|
ret:
|
||||||
|
@ -67,38 +67,6 @@ static ulong atoi_octal(const char *str)
|
|||||||
MYSQL_FILE *mysql_stdin= NULL;
|
MYSQL_FILE *mysql_stdin= NULL;
|
||||||
static MYSQL_FILE instrumented_stdin;
|
static MYSQL_FILE instrumented_stdin;
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
UINT orig_console_cp, orig_console_output_cp;
|
|
||||||
|
|
||||||
static void reset_console_cp(void)
|
|
||||||
{
|
|
||||||
SetConsoleCP(orig_console_cp);
|
|
||||||
SetConsoleOutputCP(orig_console_output_cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
The below fixes discrepancies in console output and
|
|
||||||
command line parameter encoding. command line is in
|
|
||||||
ANSI codepage, output to console by default is in OEM, but
|
|
||||||
we like them to be in the same encoding.
|
|
||||||
|
|
||||||
We do this only if current codepage is UTF8, i.e when we
|
|
||||||
know we're on Windows that can handle UTF8 well.
|
|
||||||
*/
|
|
||||||
static void set_console_cp()
|
|
||||||
{
|
|
||||||
UINT acp= GetACP();
|
|
||||||
if (acp == CP_UTF8 && !getenv("MARIADB_DISABLE_UTF8_CONSOLE"))
|
|
||||||
{
|
|
||||||
orig_console_cp= GetConsoleCP();
|
|
||||||
SetConsoleCP(acp);
|
|
||||||
orig_console_output_cp= GetConsoleOutputCP();
|
|
||||||
SetConsoleOutputCP(acp);
|
|
||||||
atexit(reset_console_cp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize my_sys functions, resources and variables
|
Initialize my_sys functions, resources and variables
|
||||||
|
|
||||||
@ -163,7 +131,6 @@ my_bool my_init(void)
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (win32_init_tcp_ip())
|
if (win32_init_tcp_ip())
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
set_console_cp();
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CHECK_UNLIKELY
|
#ifdef CHECK_UNLIKELY
|
||||||
init_my_likely();
|
init_my_likely();
|
||||||
|
@ -481,11 +481,10 @@ IF(WIN32)
|
|||||||
MYSQL_ADD_EXECUTABLE(mariadb-install-db
|
MYSQL_ADD_EXECUTABLE(mariadb-install-db
|
||||||
mysql_install_db.cc
|
mysql_install_db.cc
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/mysql_bootstrap_sql.c
|
${CMAKE_CURRENT_BINARY_DIR}/mysql_bootstrap_sql.c
|
||||||
password.c
|
|
||||||
COMPONENT Server
|
COMPONENT Server
|
||||||
)
|
)
|
||||||
SET_TARGET_PROPERTIES(mariadb-install-db PROPERTIES COMPILE_FLAGS -DINSTALL_PLUGINDIR=${INSTALL_PLUGINDIR})
|
SET_TARGET_PROPERTIES(mariadb-install-db PROPERTIES COMPILE_FLAGS -DINSTALL_PLUGINDIR=${INSTALL_PLUGINDIR})
|
||||||
TARGET_LINK_LIBRARIES(mariadb-install-db mysys mysys_ssl shlwapi)
|
TARGET_LINK_LIBRARIES(mariadb-install-db mysys shlwapi)
|
||||||
|
|
||||||
ADD_LIBRARY(winservice STATIC winservice.c)
|
ADD_LIBRARY(winservice STATIC winservice.c)
|
||||||
TARGET_LINK_LIBRARIES(winservice shell32)
|
TARGET_LINK_LIBRARIES(winservice shell32)
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "mariadb.h"
|
#include "mariadb.h"
|
||||||
#include <my_getopt.h>
|
#include <my_getopt.h>
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
#include <password.h>
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
@ -31,7 +30,6 @@
|
|||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
struct IUnknown;
|
struct IUnknown;
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <winservice.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -444,14 +442,16 @@ static int create_myini()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static constexpr const char* update_root_passwd=
|
static const char update_root_passwd_part1[]=
|
||||||
"UPDATE mysql.global_priv SET priv=json_set(priv,"
|
"UPDATE mysql.global_priv SET priv=json_set(priv,"
|
||||||
"'$.password_last_changed', UNIX_TIMESTAMP(),"
|
"'$.password_last_changed', UNIX_TIMESTAMP(),"
|
||||||
"'$.plugin','mysql_native_password',"
|
"'$.plugin','mysql_native_password',"
|
||||||
"'$.authentication_string','%s') where User='root';\n";
|
"'$.authentication_string',PASSWORD(";
|
||||||
static constexpr char remove_default_user_cmd[]=
|
static const char update_root_passwd_part2[]=
|
||||||
|
")) where User='root';\n";
|
||||||
|
static const char remove_default_user_cmd[]=
|
||||||
"DELETE FROM mysql.user where User='';\n";
|
"DELETE FROM mysql.user where User='';\n";
|
||||||
static constexpr char allow_remote_root_access_cmd[]=
|
static const char allow_remote_root_access_cmd[]=
|
||||||
"CREATE TEMPORARY TABLE tmp_user LIKE global_priv;\n"
|
"CREATE TEMPORARY TABLE tmp_user LIKE global_priv;\n"
|
||||||
"INSERT INTO tmp_user SELECT * from global_priv where user='root' "
|
"INSERT INTO tmp_user SELECT * from global_priv where user='root' "
|
||||||
" AND host='localhost';\n"
|
" AND host='localhost';\n"
|
||||||
@ -870,10 +870,18 @@ static int create_db_instance(const char *datadir)
|
|||||||
/* Change root password if requested. */
|
/* Change root password if requested. */
|
||||||
if (opt_password && opt_password[0])
|
if (opt_password && opt_password[0])
|
||||||
{
|
{
|
||||||
verbose("Setting root password");
|
verbose("Setting root password",remove_default_user_cmd);
|
||||||
char buf[2 * MY_SHA1_HASH_SIZE + 2];
|
fputs(update_root_passwd_part1, in);
|
||||||
my_make_scrambled_password(buf, opt_password, strlen(opt_password));
|
|
||||||
fprintf(in, update_root_passwd, buf);
|
/* Use hex encoding for password, to avoid escaping problems.*/
|
||||||
|
fputc('0', in);
|
||||||
|
fputc('x', in);
|
||||||
|
for(int i= 0; opt_password[i]; i++)
|
||||||
|
{
|
||||||
|
fprintf(in,"%02x",opt_password[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs(update_root_passwd_part2, in);
|
||||||
fflush(in);
|
fflush(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,6 +366,7 @@ static void get_service_config()
|
|||||||
*/
|
*/
|
||||||
static void change_service_config()
|
static void change_service_config()
|
||||||
{
|
{
|
||||||
|
char defaults_file[MAX_PATH];
|
||||||
char default_character_set[64];
|
char default_character_set[64];
|
||||||
char buf[MAX_PATH];
|
char buf[MAX_PATH];
|
||||||
char commandline[3 * MAX_PATH + 19];
|
char commandline[3 * MAX_PATH + 19];
|
||||||
@ -375,17 +376,13 @@ static void change_service_config()
|
|||||||
Write datadir to my.ini, after converting backslashes to
|
Write datadir to my.ini, after converting backslashes to
|
||||||
unix style slashes.
|
unix style slashes.
|
||||||
*/
|
*/
|
||||||
if (service_properties.datadir[0])
|
strcpy_s(buf, MAX_PATH, service_properties.datadir);
|
||||||
|
for(i= 0; buf[i]; i++)
|
||||||
{
|
{
|
||||||
strcpy_s(buf, MAX_PATH, service_properties.datadir);
|
if (buf[i] == '\\')
|
||||||
for (i= 0; buf[i]; i++)
|
buf[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
|
Remove basedir from defaults file, otherwise the service wont come up in
|
||||||
@ -400,19 +397,19 @@ static void change_service_config()
|
|||||||
*/
|
*/
|
||||||
default_character_set[0]= 0;
|
default_character_set[0]= 0;
|
||||||
GetPrivateProfileString("mysqld", "default-character-set", NULL,
|
GetPrivateProfileString("mysqld", "default-character-set", NULL,
|
||||||
default_character_set, sizeof(default_character_set), service_properties.inifile);
|
default_character_set, sizeof(default_character_set), defaults_file);
|
||||||
if (default_character_set[0])
|
if (default_character_set[0])
|
||||||
{
|
{
|
||||||
WritePrivateProfileString("mysqld", "default-character-set", NULL,
|
WritePrivateProfileString("mysqld", "default-character-set", NULL,
|
||||||
service_properties.inifile);
|
defaults_file);
|
||||||
WritePrivateProfileString("mysqld", "character-set-server",
|
WritePrivateProfileString("mysqld", "character-set-server",
|
||||||
default_character_set, service_properties.inifile);
|
default_character_set, defaults_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(defaults_file_param,"--defaults-file=%s", service_properties.inifile);
|
sprintf(defaults_file_param,"--defaults-file=%s", service_properties.inifile);
|
||||||
sprintf_s(commandline, "\"%s\" \"%s\" \"%s\"", mysqld_path,
|
sprintf_s(commandline, "\"%s\" \"%s\" \"%s\"", mysqld_path,
|
||||||
defaults_file_param, opt_service);
|
defaults_file_param, opt_service);
|
||||||
if (!my_ChangeServiceConfig(service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
|
if (!ChangeServiceConfig(service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
|
||||||
SERVICE_NO_CHANGE, commandline, NULL, NULL, NULL, NULL, NULL, NULL))
|
SERVICE_NO_CHANGE, commandline, NULL, NULL, NULL, NULL, NULL, NULL))
|
||||||
{
|
{
|
||||||
die("ChangeServiceConfig failed with %u", GetLastError());
|
die("ChangeServiceConfig failed with %u", GetLastError());
|
||||||
@ -486,8 +483,13 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
old_mysqld_exe_exists= (GetFileAttributes(service_properties.mysqld_exe) !=
|
old_mysqld_exe_exists = (GetFileAttributes(service_properties.mysqld_exe) != INVALID_FILE_ATTRIBUTES);
|
||||||
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);
|
||||||
|
|
||||||
bool do_start_stop_server = old_mysqld_exe_exists && initial_service_state != SERVICE_RUNNING;
|
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,
|
log("Phase %d/%d: Start and stop server in the old version, to avoid crash recovery %s", ++phase, max_phases,
|
||||||
@ -542,14 +544,6 @@ int main(int argc, char **argv)
|
|||||||
start_duration_ms += 500;
|
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
|
Start mysqld.exe as non-service skipping privileges (so we do not
|
||||||
care about the password). But disable networking and enable pipe
|
care about the password). But disable networking and enable pipe
|
||||||
|
@ -127,7 +127,6 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <handle_connections_win.h>
|
#include <handle_connections_win.h>
|
||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
#include <winservice.h> /* SERVICE_STOPPED, SERVICE_RUNNING etc */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <my_service_manager.h>
|
#include <my_service_manager.h>
|
||||||
|
@ -158,196 +158,51 @@ static int cmp_strings(const void* a, const void *b)
|
|||||||
return strcmp((const char *)a, *(const char **)b);
|
return strcmp((const char *)a, *(const char **)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_utf8_str(const char *s)
|
|
||||||
{
|
|
||||||
const unsigned char *bytes= (const unsigned char *) s;
|
|
||||||
int num;
|
|
||||||
|
|
||||||
while (*bytes)
|
|
||||||
{
|
|
||||||
if ((*bytes & 0x80) == 0x00)
|
|
||||||
num= 1;
|
|
||||||
else if ((*bytes & 0xE0) == 0xC0)
|
|
||||||
num= 2;
|
|
||||||
else if ((*bytes & 0xF0) == 0xE0)
|
|
||||||
num= 3;
|
|
||||||
else if ((*bytes & 0xF8) == 0xF0)
|
|
||||||
num= 4;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bytes++;
|
|
||||||
for (int i= 1; i < num; i++)
|
|
||||||
{
|
|
||||||
if ((*bytes & 0xC0) != 0x80)
|
|
||||||
return false;
|
|
||||||
bytes++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static UINT get_system_acp()
|
|
||||||
{
|
|
||||||
static DWORD system_acp;
|
|
||||||
if (system_acp)
|
|
||||||
return system_acp;
|
|
||||||
|
|
||||||
char str_cp[10];
|
|
||||||
int cch= GetLocaleInfo(GetSystemDefaultLCID(), LOCALE_IDEFAULTANSICODEPAGE,
|
|
||||||
str_cp, sizeof(str_cp));
|
|
||||||
|
|
||||||
system_acp= cch > 0 ? atoi(str_cp) : 1252;
|
|
||||||
|
|
||||||
return system_acp;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MY_INI_SECTION_SIZE 32 * 1024 + 3
|
|
||||||
|
|
||||||
static char *ansi_to_utf8(const char *s)
|
|
||||||
{
|
|
||||||
#define MAX_STR_LEN MY_INI_SECTION_SIZE
|
|
||||||
static wchar_t utf16_buf[MAX_STR_LEN];
|
|
||||||
static char utf8_buf[MAX_STR_LEN];
|
|
||||||
if (MultiByteToWideChar(get_system_acp(), 0, s, -1, utf16_buf, MAX_STR_LEN))
|
|
||||||
{
|
|
||||||
if (WideCharToMultiByte(CP_UTF8, 0, utf16_buf, -1, utf8_buf, MAX_STR_LEN,
|
|
||||||
0, 0))
|
|
||||||
return utf8_buf;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int fix_section(const char *myini_path, const char *section_name,
|
|
||||||
bool is_server)
|
|
||||||
{
|
|
||||||
if (!is_server && GetACP() != CP_UTF8)
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
value= key_end + 1;
|
|
||||||
if (GetACP() == CP_UTF8 && !is_utf8_str(value))
|
|
||||||
{
|
|
||||||
char *new_val= ansi_to_utf8(value);
|
|
||||||
if (new_val)
|
|
||||||
{
|
|
||||||
*key_end= 0;
|
|
||||||
fprintf(stdout, "Fixing variable '%s' charset, value=%s\n", keyval,
|
|
||||||
new_val);
|
|
||||||
WritePrivateProfileString(section_name, keyval, new_val, myini_path);
|
|
||||||
*key_end= '=';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!is_server)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
*q= 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*q= (*p == '-') ? '_' : *p;
|
|
||||||
}
|
|
||||||
const char *v= (const char *) bsearch(varname, removed_variables, sizeof(removed_variables) / sizeof(removed_variables[0]),
|
|
||||||
sizeof(char *), cmp_strings);
|
|
||||||
|
|
||||||
if (v)
|
|
||||||
{
|
|
||||||
fprintf(stdout, "Removing variable '%s' from config file\n", varname);
|
|
||||||
// delete variable
|
|
||||||
*key_end= 0;
|
|
||||||
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
|
Convert file from a previous version, by removing
|
||||||
Also, fix values to be UTF8, if MariaDB is running in utf8 mode
|
|
||||||
*/
|
*/
|
||||||
int upgrade_config_file(const char *myini_path)
|
int upgrade_config_file(const char *myini_path)
|
||||||
{
|
{
|
||||||
static char all_sections[MY_INI_SECTION_SIZE];
|
#define MY_INI_SECTION_SIZE 32*1024 +3
|
||||||
int sz= GetPrivateProfileSectionNamesA(all_sections, MY_INI_SECTION_SIZE,
|
static char section_data[MY_INI_SECTION_SIZE];
|
||||||
myini_path);
|
for (const char *section_name : { "mysqld","server","mariadb" })
|
||||||
if (!sz)
|
|
||||||
return 0;
|
|
||||||
if (sz > MY_INI_SECTION_SIZE - 2)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Too many sections in config file\n");
|
DWORD size = GetPrivateProfileSection(section_name, section_data, MY_INI_SECTION_SIZE, myini_path);
|
||||||
return -1;
|
if (size == MY_INI_SECTION_SIZE - 2)
|
||||||
}
|
{
|
||||||
for (char *section= all_sections; *section; section+= strlen(section) + 1)
|
return -1;
|
||||||
{
|
}
|
||||||
bool is_server_section;
|
|
||||||
if (is_mariadb_section(section, &is_server_section))
|
for (char *keyval = section_data; *keyval; keyval += strlen(keyval) + 1)
|
||||||
fix_section(myini_path, section, is_server_section);
|
{
|
||||||
|
char varname[256];
|
||||||
|
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
|
||||||
|
for (char *p = keyval, *q = varname;; p++,q++)
|
||||||
|
{
|
||||||
|
if (p == key_end)
|
||||||
|
{
|
||||||
|
*q = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*q = (*p == '-') ? '_' : *p;
|
||||||
|
}
|
||||||
|
const char *v = (const char *)bsearch(varname, removed_variables, sizeof(removed_variables) / sizeof(removed_variables[0]),
|
||||||
|
sizeof(char *), cmp_strings);
|
||||||
|
|
||||||
|
if (v)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Removing variable '%s' from config file\n", varname);
|
||||||
|
// delete variable
|
||||||
|
*key_end = 0;
|
||||||
|
WritePrivateProfileString(section_name, keyval, 0, myini_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAIN
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc != 2)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Usage : %s <config_file>\n", argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int rc= upgrade_config_file(argv[1]);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "upgrade_config_file(\"%s\") returned an error\n",
|
|
||||||
argv[1]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <winservice.h>
|
|
||||||
|
|
||||||
static SERVICE_STATUS svc_status{SERVICE_WIN32_OWN_PROCESS};
|
static SERVICE_STATUS svc_status{SERVICE_WIN32_OWN_PROCESS};
|
||||||
static SERVICE_STATUS_HANDLE svc_status_handle;
|
static SERVICE_STATUS_HANDLE svc_status_handle;
|
||||||
|
@ -134,20 +134,6 @@ 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.
|
Retrieve some properties from windows mysqld service binary path.
|
||||||
We're interested in ini file location and datadir, and also in version of
|
We're interested in ini file location and datadir, and also in version of
|
||||||
@ -197,7 +183,7 @@ int get_mysql_service_properties(const wchar_t *bin_path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Last parameter is the service name*/
|
/* Last parameter is the service name*/
|
||||||
WideCharToMultiByte(CP_ACP, 0, args[numargs - 1], -1, service_name, MAX_PATH, NULL, NULL);
|
wcstombs(service_name, args[numargs-1], MAX_PATH);
|
||||||
|
|
||||||
if(have_inifile && wcsncmp(args[1], L"--defaults-file=", 16) != 0)
|
if(have_inifile && wcsncmp(args[1], L"--defaults-file=", 16) != 0)
|
||||||
goto end;
|
goto end;
|
||||||
@ -216,7 +202,7 @@ int get_mysql_service_properties(const wchar_t *bin_path,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
WideCharToMultiByte(CP_ACP, 0, mysqld_path, -1, props->mysqld_exe, MAX_PATH, NULL, NULL);
|
wcstombs(props->mysqld_exe, mysqld_path, MAX_PATH);
|
||||||
/* If mysqld.exe exists, try to get its version from executable */
|
/* If mysqld.exe exists, try to get its version from executable */
|
||||||
if (GetFileAttributes(props->mysqld_exe) != INVALID_FILE_ATTRIBUTES)
|
if (GetFileAttributes(props->mysqld_exe) != INVALID_FILE_ATTRIBUTES)
|
||||||
{
|
{
|
||||||
@ -227,8 +213,7 @@ int get_mysql_service_properties(const wchar_t *bin_path,
|
|||||||
if (have_inifile)
|
if (have_inifile)
|
||||||
{
|
{
|
||||||
/* We have --defaults-file in service definition. */
|
/* We have --defaults-file in service definition. */
|
||||||
WideCharToMultiByte(CP_ACP, 0, args[1] + 16, -1, props->inifile,
|
wcstombs(props->inifile, args[1]+16, MAX_PATH);
|
||||||
MAX_PATH, NULL, NULL);
|
|
||||||
normalize_path(props->inifile, MAX_PATH);
|
normalize_path(props->inifile, MAX_PATH);
|
||||||
if (GetFileAttributes(props->inifile) != INVALID_FILE_ATTRIBUTES)
|
if (GetFileAttributes(props->inifile) != INVALID_FILE_ATTRIBUTES)
|
||||||
{
|
{
|
||||||
@ -299,9 +284,16 @@ int get_mysql_service_properties(const wchar_t *bin_path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props->datadir[0] == 0 || fix_and_check_datadir(props))
|
if (props->datadir[0])
|
||||||
{
|
{
|
||||||
/* There is no datadir in ini file, or non-existing dir, bail out.*/
|
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.*/
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
170
sql/winservice.h
170
sql/winservice.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2011, 2021 Monty Program Ab
|
Copyright (c) 2011, 2012, Monty Program Ab
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -21,9 +21,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#pragma warning(suppress : 4995)
|
|
||||||
#include <winsvc.h>
|
|
||||||
typedef struct mysqld_service_properties_st
|
typedef struct mysqld_service_properties_st
|
||||||
{
|
{
|
||||||
char mysqld_exe[MAX_PATH];
|
char mysqld_exe[MAX_PATH];
|
||||||
@ -34,171 +32,9 @@ typedef struct mysqld_service_properties_st
|
|||||||
int version_patch;
|
int version_patch;
|
||||||
} mysqld_service_properties;
|
} mysqld_service_properties;
|
||||||
|
|
||||||
extern int get_mysql_service_properties(const wchar_t *bin_path,
|
extern int get_mysql_service_properties(const wchar_t *bin_path,
|
||||||
mysqld_service_properties *props);
|
mysqld_service_properties *props);
|
||||||
|
|
||||||
|
|
||||||
#if !defined(UNICODE)
|
|
||||||
#include <malloc.h>
|
|
||||||
/*
|
|
||||||
The following wrappers workaround Windows bugs
|
|
||||||
with CreateService/OpenService with ANSI codepage UTF8.
|
|
||||||
|
|
||||||
Apparently, these function in ANSI mode, for this codepage only
|
|
||||||
do *not* behave as expected (as-if string parameters were
|
|
||||||
converted to UTF16 and "wide" function were called)
|
|
||||||
*/
|
|
||||||
static inline wchar_t* awstrdup(const char *str)
|
|
||||||
{
|
|
||||||
if (!str)
|
|
||||||
return NULL;
|
|
||||||
size_t len= strlen(str) + 1;
|
|
||||||
wchar_t *wstr= (wchar_t *) malloc(sizeof(wchar_t)*len);
|
|
||||||
if (MultiByteToWideChar(CP_ACP, 0, str, (int)len, wstr, (int)len) == 0)
|
|
||||||
{
|
|
||||||
free(wstr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return wstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define AWSTRDUP(dest, src) \
|
|
||||||
dest= awstrdup(src); \
|
|
||||||
if (src && !dest) \
|
|
||||||
{ \
|
|
||||||
ok= FALSE; \
|
|
||||||
last_error = ERROR_OUTOFMEMORY; \
|
|
||||||
goto end; \
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline SC_HANDLE my_OpenService(SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAccess)
|
|
||||||
{
|
|
||||||
wchar_t *w_ServiceName= NULL;
|
|
||||||
BOOL ok=TRUE;
|
|
||||||
DWORD last_error;
|
|
||||||
SC_HANDLE sch;
|
|
||||||
|
|
||||||
AWSTRDUP(w_ServiceName, lpServiceName);
|
|
||||||
sch= OpenServiceW(hSCManager, w_servicename, dwDesiredAccess);
|
|
||||||
if (!sch)
|
|
||||||
{
|
|
||||||
ok= FALSE;
|
|
||||||
last_error= GetLastError();
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
free(w_ServiceName);
|
|
||||||
if (!ret)
|
|
||||||
SetLastError(last_error);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline SC_HANDLE my_CreateService(SC_HANDLE hSCManager,
|
|
||||||
LPCSTR lpServiceName, LPCSTR lpDisplayName,
|
|
||||||
DWORD dwDesiredAccess, DWORD dwServiceType,
|
|
||||||
DWORD dwStartType, DWORD dwErrorControl,
|
|
||||||
LPCSTR lpBinaryPathName, LPCSTR lpLoadOrderGroup,
|
|
||||||
LPDWORD lpdwTagId, LPCSTR lpDependencies,
|
|
||||||
LPCSTR lpServiceStartName, LPCSTR lpPassword)
|
|
||||||
{
|
|
||||||
wchar_t *w_ServiceName= NULL;
|
|
||||||
wchar_t *w_DisplayName= NULL;
|
|
||||||
wchar_t *w_BinaryPathName= NULL;
|
|
||||||
wchar_t *w_LoadOrderGroup= NULL;
|
|
||||||
wchar_t *w_Depedencies= NULL;
|
|
||||||
wchar_t *w_ServiceStartName= NULL;
|
|
||||||
wchar_t *w_Password= NULL;
|
|
||||||
SC_HANDLE sch;
|
|
||||||
DWORD last_error;
|
|
||||||
BOOL ok= TRUE;
|
|
||||||
|
|
||||||
AWSTRDUP(w_ServiceName,lpServiceName);
|
|
||||||
AWSTRDUP(w_DisplayName,lpDisplayName);
|
|
||||||
AWSTRDUP(w_BinaryPathName, lpBinaryPathName);
|
|
||||||
AWSTRDUP(w_LoadOrderGroup, lpLoadOrderGroup);
|
|
||||||
AWSTRDUP(w_Dependencies, lpDependencies);
|
|
||||||
AWSTRDUP(w_ServiceStartName, lpServiceStartName);
|
|
||||||
AWSTRDUP(w_Password, lpPassword);
|
|
||||||
|
|
||||||
sch= CreateServiceW(
|
|
||||||
hSCManager, w_ServiceName, w_DisplayName, dwDesiredAccess, dwServiceType,
|
|
||||||
dwStartType, dwErrorControl, w_BinaryPathName, w_LoadOrderGroup,
|
|
||||||
lpdwTagId, w_Depedencies, w_ServiceStartName, w_Password);
|
|
||||||
if(!sch)
|
|
||||||
{
|
|
||||||
ok= FALSE;
|
|
||||||
last_error= GetLastError();
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
free(w_ServiceName);
|
|
||||||
free(w_DisplayName);
|
|
||||||
free(w_BinaryPathName);
|
|
||||||
free(w_LoadOrderGroup);
|
|
||||||
free(w_Depedencies);
|
|
||||||
free(w_ServiceStartName);
|
|
||||||
free(w_Password);
|
|
||||||
|
|
||||||
if (!ok)
|
|
||||||
SetLastError(last_error);
|
|
||||||
return sch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline BOOL my_ChangeServiceConfig(SC_HANDLE hService, DWORD dwServiceType,
|
|
||||||
DWORD dwStartType, DWORD dwErrorControl,
|
|
||||||
LPCSTR lpBinaryPathName, LPCSTR lpLoadOrderGroup,
|
|
||||||
LPDWORD lpdwTagId, LPCSTR lpDependencies,
|
|
||||||
LPCSTR lpServiceStartName, LPCSTR lpPassword,
|
|
||||||
LPCSTR lpDisplayName)
|
|
||||||
{
|
|
||||||
wchar_t *w_DisplayName= NULL;
|
|
||||||
wchar_t *w_BinaryPathName= NULL;
|
|
||||||
wchar_t *w_LoadOrderGroup= NULL;
|
|
||||||
wchar_t *w_Depedencies= NULL;
|
|
||||||
wchar_t *w_ServiceStartName= NULL;
|
|
||||||
wchar_t *w_Password= NULL;
|
|
||||||
SC_HANDLE sch;
|
|
||||||
DWORD last_error;
|
|
||||||
BOOL ok= TRUE;
|
|
||||||
|
|
||||||
AWSTRDUP(w_DisplayName, lpDisplayName);
|
|
||||||
AWSTRDUP(w_BinaryPathName, lpBinaryPathName);
|
|
||||||
AWSTRDUP(w_LoadOrderGroup, lpLoadOrderGroup);
|
|
||||||
AWSTRDUP(w_Dependencies, lpDependencies);
|
|
||||||
AWSTRDUP(w_ServiceStartName, lpServiceStartName);
|
|
||||||
AWSTRDUP(w_Password, lpPassword);
|
|
||||||
|
|
||||||
ok= ChangeServiceConfigW(
|
|
||||||
hService, dwServiceType, dwStartType, dwErrorControl, w_BinaryPathName,
|
|
||||||
w_LoadOrderGroup, lpdwTagId, w_Depedencies, w_ServiceStartName,
|
|
||||||
w_Password, w_DisplayName);
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
last_error= GetLastError();
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
free(w_DisplayName);
|
|
||||||
free(w_BinaryPathName);
|
|
||||||
free(w_LoadOrderGroup);
|
|
||||||
free(w_Depedencies);
|
|
||||||
free(w_ServiceStartName);
|
|
||||||
free(w_Password);
|
|
||||||
|
|
||||||
if (last_error)
|
|
||||||
SetLastError(last_error);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#undef AWSTRDUP
|
|
||||||
|
|
||||||
#undef OpenService
|
|
||||||
#define OpenService my_OpenService
|
|
||||||
#undef ChangeServiceConfig
|
|
||||||
#define ChangeServiceConfig my_ChangeServiceConfig
|
|
||||||
#undef CreateService
|
|
||||||
#define CreateService my_CreateService
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -461,7 +461,7 @@
|
|||||||
Section="mysqld"
|
Section="mysqld"
|
||||||
Name="my.ini"
|
Name="my.ini"
|
||||||
Key="character-set-server"
|
Key="character-set-server"
|
||||||
Value="utf8mb4" />
|
Value="utf8" />
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- Shortcuts in program menu (mysql client etc) -->
|
<!-- Shortcuts in program menu (mysql client etc) -->
|
||||||
|
@ -5,7 +5,6 @@ ENDIF()
|
|||||||
# We need MFC
|
# We need MFC
|
||||||
# /permissive- flag does not play well with MFC, disable it.
|
# /permissive- flag does not play well with MFC, disable it.
|
||||||
STRING(REPLACE "/permissive-" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
STRING(REPLACE "/permissive-" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||||
REMOVE_DEFINITIONS(-DNOSERVICE) # fixes "already defined" warning in an AFX header
|
|
||||||
|
|
||||||
FIND_PACKAGE(MFC)
|
FIND_PACKAGE(MFC)
|
||||||
IF(NOT MFC_FOUND)
|
IF(NOT MFC_FOUND)
|
||||||
|
@ -141,24 +141,24 @@ void CUpgradeDlg::PopulateServicesList()
|
|||||||
ErrorExit("OpenSCManager failed");
|
ErrorExit("OpenSCManager failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
static BYTE buf[2*64*1024];
|
static BYTE buf[64*1024];
|
||||||
static BYTE configBuffer[8*1024];
|
static BYTE configBuffer[8*1024];
|
||||||
|
|
||||||
DWORD bufsize= sizeof(buf);
|
DWORD bufsize= sizeof(buf);
|
||||||
DWORD bufneed;
|
DWORD bufneed;
|
||||||
DWORD num_services;
|
DWORD num_services;
|
||||||
BOOL ok= EnumServicesStatusExW(scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32,
|
BOOL ok= EnumServicesStatusEx(scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32,
|
||||||
SERVICE_STATE_ALL, buf, bufsize, &bufneed, &num_services, NULL, NULL);
|
SERVICE_STATE_ALL, buf, bufsize, &bufneed, &num_services, NULL, NULL);
|
||||||
if(!ok)
|
if(!ok)
|
||||||
ErrorExit("EnumServicesStatusEx failed");
|
ErrorExit("EnumServicesStatusEx failed");
|
||||||
|
|
||||||
|
|
||||||
LPENUM_SERVICE_STATUS_PROCESSW info =
|
LPENUM_SERVICE_STATUS_PROCESS info =
|
||||||
(LPENUM_SERVICE_STATUS_PROCESSW)buf;
|
(LPENUM_SERVICE_STATUS_PROCESS)buf;
|
||||||
int index=-1;
|
int index=-1;
|
||||||
for (ULONG i=0; i < num_services; i++)
|
for (ULONG i=0; i < num_services; i++)
|
||||||
{
|
{
|
||||||
SC_HANDLE service= OpenServiceW(scm, info[i].lpServiceName,
|
SC_HANDLE service= OpenService(scm, info[i].lpServiceName,
|
||||||
SERVICE_QUERY_CONFIG);
|
SERVICE_QUERY_CONFIG);
|
||||||
if (!service)
|
if (!service)
|
||||||
continue;
|
continue;
|
||||||
@ -187,11 +187,7 @@ void CUpgradeDlg::PopulateServicesList()
|
|||||||
ServiceProperties props;
|
ServiceProperties props;
|
||||||
props.myini= service_props.inifile;
|
props.myini= service_props.inifile;
|
||||||
props.datadir= service_props.datadir;
|
props.datadir= service_props.datadir;
|
||||||
char service_name_buf[1024];
|
props.servicename = info[i].lpServiceName;
|
||||||
WideCharToMultiByte(CP_ACP, 0, info[i].lpServiceName, -1,
|
|
||||||
service_name_buf, sizeof(service_name_buf),
|
|
||||||
0, 0);
|
|
||||||
props.servicename= service_name_buf;
|
|
||||||
if (service_props.version_major)
|
if (service_props.version_major)
|
||||||
{
|
{
|
||||||
char ver[64];
|
char ver[64];
|
||||||
@ -202,7 +198,7 @@ void CUpgradeDlg::PopulateServicesList()
|
|||||||
else
|
else
|
||||||
props.version= "<unknown>";
|
props.version= "<unknown>";
|
||||||
|
|
||||||
index = m_Services.AddString(service_name_buf);
|
index = m_Services.AddString(info[i].lpServiceName);
|
||||||
services.resize(index+1);
|
services.resize(index+1);
|
||||||
services[index] = props;
|
services[index] = props;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user