summaryrefslogtreecommitdiff
path: root/sql-common
diff options
context:
space:
mode:
Diffstat (limited to 'sql-common')
-rw-r--r--sql-common/Makefile.am17
-rw-r--r--sql-common/client.c1203
-rw-r--r--sql-common/client_plugin.c111
-rw-r--r--sql-common/my_time.c31
-rw-r--r--sql-common/my_user.c5
5 files changed, 880 insertions, 487 deletions
diff --git a/sql-common/Makefile.am b/sql-common/Makefile.am
deleted file mode 100644
index 2f5a049085f..00000000000
--- a/sql-common/Makefile.am
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (C) 2003-2004, 2006 MySQL AB
-#
-# 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
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-## Process this file with automake to create Makefile.in
-EXTRA_DIST = client.c pack.c my_time.c my_user.c client_plugin.c
diff --git a/sql-common/client.c b/sql-common/client.c
index 902bd658ee7..638dab9afc4 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -24,7 +24,6 @@
mysql_real_connect()
- Support for reading local file with LOAD DATA LOCAL
- SHARED memory handling
- - Protection against sigpipe
- Prepared statements
- Things that only works for the server
@@ -38,6 +37,10 @@
#include "mysql.h"
+#ifndef __WIN__
+#include <netdb.h>
+#endif
+
/* Remove client convenience wrappers */
#undef max_allowed_packet
#undef net_buffer_length
@@ -66,9 +69,9 @@ my_bool net_flush(NET *net);
#include "mysqld_error.h"
#include "errmsg.h"
#include <violite.h>
-#if defined(THREAD) && !defined(__WIN__)
+#if !defined(__WIN__)
#include <my_pthread.h> /* because of signal() */
-#endif /* defined(THREAD) && !defined(__WIN__) */
+#endif /* !defined(__WIN__) */
#include <sys/stat.h>
#include <signal.h>
@@ -76,7 +79,7 @@ my_bool net_flush(NET *net);
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
-#if !defined(MSDOS) && !defined(__WIN__)
+#if !defined(__WIN__)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -87,12 +90,12 @@ my_bool net_flush(NET *net);
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
-#endif /*!defined(MSDOS) && !defined(__WIN__) */
+#endif /* !defined(__WIN__) */
#ifdef HAVE_SYS_UN_H
# include <sys/un.h>
#endif
-#if defined(MSDOS) || defined(__WIN__)
+#if defined(__WIN__)
#define perror(A)
#else
#include <errno.h>
@@ -127,7 +130,7 @@ static void mysql_close_free(MYSQL *mysql);
static void mysql_prune_stmt_list(MYSQL *mysql);
static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length);
-#if !(defined(__WIN__) || defined(__NETWARE__))
+#if !defined(__WIN__)
static int wait_for_data(my_socket fd, uint timeout);
#endif
@@ -149,10 +152,13 @@ char mysql_server_last_error[MYSQL_ERRMSG_SIZE];
int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
uint timeout)
{
-#if defined(__WIN__) || defined(__NETWARE__)
- return connect(fd, (struct sockaddr*) name, namelen);
+#if defined(__WIN__)
+ DBUG_ENTER("my_connect");
+ DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen));
#else
int flags, res, s_err;
+ DBUG_ENTER("my_connect");
+ DBUG_PRINT("enter", ("fd: %d timeout: %u", fd, timeout));
/*
If they passed us a timeout of zero, we should behave
@@ -160,24 +166,26 @@ int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
*/
if (timeout == 0)
- return connect(fd, (struct sockaddr*) name, namelen);
+ DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen));
flags = fcntl(fd, F_GETFL, 0); /* Set socket to not block */
#ifdef O_NONBLOCK
fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */
#endif
+ DBUG_PRINT("info", ("connecting non-blocking"));
res= connect(fd, (struct sockaddr*) name, namelen);
+ DBUG_PRINT("info", ("connect result: %d errno: %d", res, errno));
s_err= errno; /* Save the error... */
fcntl(fd, F_SETFL, flags);
if ((res != 0) && (s_err != EINPROGRESS))
{
errno= s_err; /* Restore it */
- return(-1);
+ DBUG_RETURN(-1);
}
if (res == 0) /* Connected quickly! */
- return(0);
- return wait_for_data(fd, timeout);
+ DBUG_RETURN(0);
+ DBUG_RETURN(wait_for_data(fd, timeout));
#endif
}
@@ -189,33 +197,65 @@ int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
If not, we will use select()
*/
-#if !(defined(__WIN__) || defined(__NETWARE__))
+#if !defined(__WIN__)
static int wait_for_data(my_socket fd, uint timeout)
{
#ifdef HAVE_POLL
struct pollfd ufds;
int res;
+ DBUG_ENTER("wait_for_data");
+ DBUG_PRINT("info", ("polling"));
ufds.fd= fd;
ufds.events= POLLIN | POLLPRI;
if (!(res= poll(&ufds, 1, (int) timeout*1000)))
{
+ DBUG_PRINT("info", ("poll timed out"));
errno= EINTR;
- return -1;
+ DBUG_RETURN(-1);
}
+ DBUG_PRINT("info",
+ ("poll result: %d errno: %d revents: 0x%02d events: 0x%02d",
+ res, errno, ufds.revents, ufds.events));
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
- return -1;
- return 0;
+ DBUG_RETURN(-1);
+ /*
+ At this point, we know that something happened on the socket.
+ But this does not means that everything is alright.
+ The connect might have failed. We need to retrieve the error code
+ from the socket layer. We must return success only if we are sure
+ that it was really a success. Otherwise we might prevent the caller
+ from trying another address to connect to.
+ */
+ {
+ int s_err;
+ socklen_t s_len= sizeof(s_err);
+
+ DBUG_PRINT("info", ("Get SO_ERROR from non-blocked connected socket."));
+ res= getsockopt(fd, SOL_SOCKET, SO_ERROR, &s_err, &s_len);
+ DBUG_PRINT("info", ("getsockopt res: %d s_err: %d", res, s_err));
+ if (res)
+ DBUG_RETURN(res);
+ /* getsockopt() was successful, check the retrieved status value. */
+ if (s_err)
+ {
+ errno= s_err;
+ DBUG_RETURN(-1);
+ }
+ /* Status from connect() is zero. Socket is successfully connected. */
+ }
+ DBUG_RETURN(0);
#else
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
fd_set sfds;
struct timeval tv;
time_t start_time, now_time;
int res, s_err;
+ DBUG_ENTER("wait_for_data");
if (fd >= FD_SETSIZE) /* Check if wrong error */
- return 0; /* Can't use timeout */
+ DBUG_RETURN(0); /* Can't use timeout */
/*
Our connection is "in progress." We can use the select() call to wait
@@ -247,7 +287,7 @@ static int wait_for_data(my_socket fd, uint timeout)
{
tv.tv_sec = (long) timeout;
tv.tv_usec = 0;
-#if defined(HPUX10) && defined(THREAD)
+#if defined(HPUX10)
if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
break;
#else
@@ -255,11 +295,11 @@ static int wait_for_data(my_socket fd, uint timeout)
break;
#endif
if (res == 0) /* timeout */
- return -1;
+ DBUG_RETURN(-1);
now_time= my_time(0);
timeout-= (uint) (now_time - start_time);
if (errno != EINTR || (int) timeout <= 0)
- return -1;
+ DBUG_RETURN(-1);
}
/*
@@ -270,17 +310,17 @@ static int wait_for_data(my_socket fd, uint timeout)
s_err=0;
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
- return(-1);
+ DBUG_RETURN(-1);
if (s_err)
{ /* getsockopt could succeed */
errno = s_err;
- return(-1); /* but return an error... */
+ DBUG_RETURN(-1); /* but return an error... */
}
- return (0); /* ok */
+ DBUG_RETURN(0); /* ok */
#endif /* HAVE_POLL */
}
-#endif /* defined(__WIN__) || defined(__NETWARE__) */
+#endif /* !defined(__WIN__) */
/**
Set the internal error message to mysql handler
@@ -652,8 +692,7 @@ err2:
CloseHandle(handle_file_map);
}
err:
- if (tmp)
- my_free(tmp, MYF(0));
+ my_free(tmp);
if (error_allow)
error_code = GetLastError();
if (event_connect_request)
@@ -678,24 +717,24 @@ err:
}
#endif
-/*****************************************************************************
+/**
Read a packet from server. Give error message if socket was down
or packet is an error message
-*****************************************************************************/
+
+ @retval packet_error An error occurred during reading.
+ Error message is set.
+ @retval
+*/
ulong
cli_safe_read(MYSQL *mysql)
{
NET *net= &mysql->net;
ulong len=0;
- init_sigpipe_variables
restart:
- /* Don't give sigpipe errors if the client doesn't want them */
- set_sigpipe(mysql);
if (net->vio != 0)
len=my_net_read(net);
- reset_sigpipe(mysql);
if (len == packet_error || len == 0)
{
@@ -777,7 +816,7 @@ void free_rows(MYSQL_DATA *cur)
if (cur)
{
free_root(&cur->alloc,MYF(0));
- my_free((uchar*) cur,MYF(0));
+ my_free(cur);
}
}
@@ -789,13 +828,9 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
{
NET *net= &mysql->net;
my_bool result= 1;
- init_sigpipe_variables
my_bool stmt_skip= stmt ? stmt->state != MYSQL_STMT_INIT_DONE : FALSE;
DBUG_ENTER("cli_advanced_command");
- /* Don't give sigpipe errors if the client doesn't want them */
- set_sigpipe(mysql);
-
if (mysql->net.vio == 0)
{ /* Do reconnect if possible */
if (mysql_reconnect(mysql) || stmt_skip)
@@ -844,7 +879,6 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
result= ((mysql->packet_length=cli_safe_read(mysql)) == packet_error ?
1 : 0);
end:
- reset_sigpipe(mysql);
DBUG_PRINT("exit",("result: %d", result));
DBUG_RETURN(result);
}
@@ -862,31 +896,132 @@ void free_old_query(MYSQL *mysql)
DBUG_VOID_RETURN;
}
+
+/**
+ Finish reading of a partial result set from the server.
+ Get the EOF packet, and update mysql->status
+ and mysql->warning_count.
+
+ @return TRUE if a communication or protocol error, an error
+ is set in this case, FALSE otherwise.
+*/
+
+my_bool flush_one_result(MYSQL *mysql)
+{
+ ulong packet_length;
+
+ DBUG_ASSERT(mysql->status != MYSQL_STATUS_READY);
+
+ do
+ {
+ packet_length= cli_safe_read(mysql);
+ /*
+ There is an error reading from the connection,
+ or (sic!) there were no error and no
+ data in the stream, i.e. no more data from the server.
+ Since we know our position in the stream (somewhere in
+ the middle of a result set), this latter case is an error too
+ -- each result set must end with a EOF packet.
+ cli_safe_read() has set an error for us, just return.
+ */
+ if (packet_length == packet_error)
+ return TRUE;
+ }
+ while (packet_length > 8 || mysql->net.read_pos[0] != 254);
+
+ /* Analyze EOF packet of the result set. */
+
+ if (protocol_41(mysql))
+ {
+ char *pos= (char*) mysql->net.read_pos + 1;
+ mysql->warning_count=uint2korr(pos);
+ pos+=2;
+ mysql->server_status=uint2korr(pos);
+ pos+=2;
+ }
+ return FALSE;
+}
+
+
+/**
+ Read a packet from network. If it's an OK packet, flush it.
+
+ @return TRUE if error, FALSE otherwise. In case of
+ success, is_ok_packet is set to TRUE or FALSE,
+ based on what we got from network.
+*/
+
+my_bool opt_flush_ok_packet(MYSQL *mysql, my_bool *is_ok_packet)
+{
+ ulong packet_length= cli_safe_read(mysql);
+
+ if (packet_length == packet_error)
+ return TRUE;
+
+ /* cli_safe_read always reads a non-empty packet. */
+ DBUG_ASSERT(packet_length);
+
+ *is_ok_packet= mysql->net.read_pos[0] == 0;
+ if (*is_ok_packet)
+ {
+ uchar *pos= mysql->net.read_pos + 1;
+
+ net_field_length_ll(&pos); /* affected rows */
+ net_field_length_ll(&pos); /* insert id */
+
+ mysql->server_status=uint2korr(pos);
+ pos+=2;
+
+ if (protocol_41(mysql))
+ {
+ mysql->warning_count=uint2korr(pos);
+ pos+=2;
+ }
+ }
+ return FALSE;
+}
+
+
/*
Flush result set sent from server
*/
-static void cli_flush_use_result(MYSQL *mysql)
+static void cli_flush_use_result(MYSQL *mysql, my_bool flush_all_results)
{
/* Clear the current execution status */
DBUG_ENTER("cli_flush_use_result");
DBUG_PRINT("warning",("Not all packets read, clearing them"));
- for (;;)
+
+ if (flush_one_result(mysql))
+ DBUG_VOID_RETURN; /* An error occurred */
+
+ if (! flush_all_results)
+ DBUG_VOID_RETURN;
+
+ while (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
{
- ulong pkt_len;
- if ((pkt_len=cli_safe_read(mysql)) == packet_error)
- break;
- if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
+ my_bool is_ok_packet;
+ if (opt_flush_ok_packet(mysql, &is_ok_packet))
+ DBUG_VOID_RETURN; /* An error occurred. */
+ if (is_ok_packet)
{
- if (protocol_41(mysql))
- {
- char *pos= (char*) mysql->net.read_pos + 1;
- mysql->warning_count=uint2korr(pos); pos+=2;
- mysql->server_status=uint2korr(pos); pos+=2;
- }
- break; /* End of data */
+ /*
+ Indeed what we got from network was an OK packet, and we
+ know that OK is the last one in a multi-result-set, so
+ just return.
+ */
+ DBUG_VOID_RETURN;
}
+ /*
+ It's a result set, not an OK packet. A result set contains
+ of two result set subsequences: field metadata, terminated
+ with EOF packet, and result set data, again terminated with
+ EOF packet. Read and flush them.
+ */
+ if (flush_one_result(mysql) || flush_one_result(mysql))
+ DBUG_VOID_RETURN; /* An error occurred. */
}
+
DBUG_VOID_RETURN;
}
@@ -943,14 +1078,11 @@ void end_server(MYSQL *mysql)
DBUG_ENTER("end_server");
if (mysql->net.vio != 0)
{
- init_sigpipe_variables
DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio)));
#ifdef MYSQL_SERVER
slave_io_thread_detach_vio();
#endif
- set_sigpipe(mysql);
vio_delete(mysql->net.vio);
- reset_sigpipe(mysql);
mysql->net.vio= 0; /* Marker */
mysql_prune_stmt_list(mysql);
}
@@ -975,7 +1107,7 @@ mysql_free_result(MYSQL_RES *result)
mysql->unbuffered_fetch_owner= 0;
if (mysql->status == MYSQL_STATUS_USE_RESULT)
{
- (*mysql->methods->flush_use_result)(mysql);
+ (*mysql->methods->flush_use_result)(mysql, FALSE);
mysql->status=MYSQL_STATUS_READY;
if (mysql->unbuffered_fetch_owner)
*mysql->unbuffered_fetch_owner= TRUE;
@@ -984,9 +1116,8 @@ mysql_free_result(MYSQL_RES *result)
free_rows(result->data);
if (result->fields)
free_root(&result->field_alloc,MYF(0));
- if (result->row)
- my_free((uchar*) result->row,MYF(0));
- my_free((uchar*) result,MYF(0));
+ my_free(result->row);
+ my_free(result);
}
DBUG_VOID_RETURN;
}
@@ -1002,7 +1133,6 @@ static const char *default_options[]=
"ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
"character-sets-dir", "default-character-set", "interactive-timeout",
"connect-timeout", "local-infile", "disable-local-infile",
- "replication-probe", "enable-reads-from-master", "repl-parse-query",
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
"multi-results", "multi-statements", "multi-queries", "secure-auth",
"report-data-truncation", "plugin-dir", "default-auth",
@@ -1014,10 +1144,10 @@ enum option_id {
OPT_ssl_key, OPT_ssl_cert, OPT_ssl_ca, OPT_ssl_capath,
OPT_character_sets_dir, OPT_default_character_set, OPT_interactive_timeout,
OPT_connect_timeout, OPT_local_infile, OPT_disable_local_infile,
- OPT_replication_probe, OPT_enable_reads_from_master, OPT_repl_parse_query,
OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name,
OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth,
OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth,
+ OPT_keep_this_one_last
};
static TYPELIB option_types={array_elements(default_options)-1,
@@ -1036,30 +1166,30 @@ static int add_init_command(struct st_mysql_options *options, const char *cmd)
{
options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
MYF(MY_WME));
- init_dynamic_array(options->init_commands,sizeof(char*),5,5 CALLER_INFO);
+ init_dynamic_array(options->init_commands,sizeof(char*),5,5);
}
if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
insert_dynamic(options->init_commands, (uchar*)&tmp))
{
- my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(tmp);
return 1;
}
return 0;
}
-#define extension_set(OPTS, X, VAL) \
+#define EXTENSION_SET(OPTS, X, VAL) \
if (!(OPTS)->extension) \
(OPTS)->extension= (struct st_mysql_options_extention *) \
my_malloc(sizeof(struct st_mysql_options_extention), \
MYF(MY_WME | MY_ZEROFILL)); \
(OPTS)->extension->X= VAL;
-#define extension_set_string(OPTS, X, STR) \
+#define EXTENSION_SET_STRING(OPTS, X, STR) \
if ((OPTS)->extension) \
- my_free((OPTS)->extension->X, MYF(MY_ALLOW_ZERO_PTR)); \
- extension_set(OPTS, X, my_strdup((STR), MYF(MY_WME)));
+ my_free((OPTS)->extension->X); \
+ EXTENSION_SET(OPTS, X, my_strdup((STR), MYF(MY_WME)));
void mysql_read_default_options(struct st_mysql_options *options,
const char *filename,const char *group)
@@ -1070,6 +1200,9 @@ void mysql_read_default_options(struct st_mysql_options *options,
DBUG_ENTER("mysql_read_default_options");
DBUG_PRINT("enter",("file: %s group: %s",filename,group ? group :"NULL"));
+ compile_time_assert(OPT_keep_this_one_last ==
+ array_elements(default_options));
+
argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
groups[0]= (char*) "client";
groups[1]= (char*) "client-server";
@@ -1083,6 +1216,8 @@ void mysql_read_default_options(struct st_mysql_options *options,
char **option=argv;
while (*++option)
{
+ if (my_getopt_is_args_separator(option[0])) /* skip arguments separator */
+ continue;
/* DBUG_PRINT("info",("option: %s",option[0])); */
if (option[0][0] == '-' && option[0][1] == '-')
{
@@ -1096,7 +1231,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
/* Change all '_' in variable name to '-' */
for (end= *option ; *(end= strcend(end,'_')) ; )
*end= '-';
- switch (find_type(*option+2,&option_types,2)) {
+ switch (find_type(*option + 2, &option_types, FIND_TYPE_BASIC)) {
case OPT_port:
if (opt_arg)
options->port=atoi(opt_arg);
@@ -1104,7 +1239,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
case OPT_socket:
if (opt_arg)
{
- my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->unix_socket);
options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
}
break;
@@ -1112,10 +1247,10 @@ void mysql_read_default_options(struct st_mysql_options *options,
options->compress=1;
options->client_flag|= CLIENT_COMPRESS;
break;
- case OPT_password:
+ case OPT_password:
if (opt_arg)
{
- my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->password);
options->password=my_strdup(opt_arg,MYF(MY_WME));
}
break;
@@ -1129,7 +1264,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
case OPT_user:
if (opt_arg)
{
- my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->user);
options->user=my_strdup(opt_arg,MYF(MY_WME));
}
break;
@@ -1139,14 +1274,14 @@ void mysql_read_default_options(struct st_mysql_options *options,
case OPT_host:
if (opt_arg)
{
- my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->host);
options->host=my_strdup(opt_arg,MYF(MY_WME));
}
break;
case OPT_database:
if (opt_arg)
{
- my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->db);
options->db=my_strdup(opt_arg,MYF(MY_WME));
}
break;
@@ -1158,25 +1293,25 @@ void mysql_read_default_options(struct st_mysql_options *options,
case OPT_return_found_rows:
options->client_flag|=CLIENT_FOUND_ROWS;
break;
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
case OPT_ssl_key:
- my_free(options->ssl_key, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->ssl_key);
options->ssl_key = my_strdup(opt_arg, MYF(MY_WME));
break;
case OPT_ssl_cert:
- my_free(options->ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->ssl_cert);
options->ssl_cert = my_strdup(opt_arg, MYF(MY_WME));
break;
case OPT_ssl_ca:
- my_free(options->ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->ssl_ca);
options->ssl_ca = my_strdup(opt_arg, MYF(MY_WME));
break;
case OPT_ssl_capath:
- my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->ssl_capath);
options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME));
break;
case OPT_ssl_cipher:
- my_free(options->ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->ssl_cipher);
options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME));
break;
#else
@@ -1186,13 +1321,13 @@ void mysql_read_default_options(struct st_mysql_options *options,
case OPT_ssl_capath:
case OPT_ssl_cipher:
break;
-#endif /* HAVE_OPENSSL */
- case OPT_character_sets_dir:
- my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
+ case OPT_character_sets_dir:
+ my_free(options->charset_dir);
options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
break;
case OPT_default_character_set:
- my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->charset_name);
options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
break;
case OPT_interactive_timeout:
@@ -1207,26 +1342,13 @@ void mysql_read_default_options(struct st_mysql_options *options,
case OPT_disable_local_infile:
options->client_flag&= ~CLIENT_LOCAL_FILES;
break;
- case OPT_replication_probe:
-#ifndef TO_BE_DELETED
- options->rpl_probe= 1;
-#endif
- break;
- case OPT_enable_reads_from_master:
- options->no_master_reads= 0;
- break;
- case OPT_repl_parse_query:
-#ifndef TO_BE_DELETED
- options->rpl_parse= 1;
-#endif
- break;
case OPT_max_allowed_packet:
if (opt_arg)
options->max_allowed_packet= atoi(opt_arg);
break;
case OPT_protocol:
- if ((options->protocol= find_type(opt_arg,
- &sql_protocol_typelib,0)) <= 0)
+ if ((options->protocol= find_type(opt_arg, &sql_protocol_typelib,
+ FIND_TYPE_BASIC)) <= 0)
{
fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg);
exit(1);
@@ -1235,7 +1357,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
case OPT_shared_memory_base_name:
#ifdef HAVE_SMEM
if (options->shared_memory_base_name != def_shared_memory_base_name)
- my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(options->shared_memory_base_name);
options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME));
#endif
break;
@@ -1253,10 +1375,22 @@ void mysql_read_default_options(struct st_mysql_options *options,
options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
break;
case OPT_plugin_dir:
- extension_set_string(options, plugin_dir, opt_arg);
+ {
+ char buff[FN_REFLEN], buff2[FN_REFLEN];
+ if (strlen(opt_arg) >= FN_REFLEN)
+ opt_arg[FN_REFLEN]= '\0';
+ if (my_realpath(buff, opt_arg, 0))
+ {
+ DBUG_PRINT("warning",("failed to normalize the plugin path: %s",
+ opt_arg));
+ break;
+ }
+ convert_dirname(buff, buff2, NULL);
+ EXTENSION_SET_STRING(options, plugin_dir, buff2);
+ }
break;
case OPT_default_auth:
- extension_set_string(options, default_auth, opt_arg);
+ EXTENSION_SET_STRING(options, default_auth, opt_arg);
break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
@@ -1349,7 +1483,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->flags= uint2korr(pos+7);
field->decimals= (uint) pos[9];
- if (INTERNAL_NUM_FIELD(field))
+ if (IS_NUM(field->type))
field->flags|= NUM_FLAG;
if (default_value && row->data[7])
{
@@ -1390,7 +1524,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->flags= (uint) (uchar) row->data[4][0];
field->decimals=(uint) (uchar) row->data[4][1];
}
- if (INTERNAL_NUM_FIELD(field))
+ if (IS_NUM(field->type))
field->flags|= NUM_FLAG;
if (default_value && row->data[5])
{
@@ -1582,16 +1716,8 @@ mysql_init(MYSQL *mysql)
else
bzero((char*) (mysql), sizeof(*(mysql)));
mysql->options.connect_timeout= CONNECT_TIMEOUT;
- mysql->last_used_con= mysql->next_slave= mysql->master = mysql;
mysql->charset=default_client_charset_info;
strmov(mysql->net.sqlstate, not_error_sqlstate);
- /*
- By default, we are a replication pivot. The caller must reset it
- after we return if this is not the case.
- */
-#ifndef TO_BE_DELETED
- mysql->rpl_pivot = 1;
-#endif
/*
Only enable LOAD DATA INFILE by default if configured with
@@ -1648,17 +1774,17 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
{
DBUG_ENTER("mysql_ssl_set");
#ifdef HAVE_OPENSSL
- my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.ssl_key);
+ my_free(mysql->options.ssl_cert);
+ my_free(mysql->options.ssl_ca);
+ my_free(mysql->options.ssl_capath);
+ my_free(mysql->options.ssl_cipher);
mysql->options.ssl_key= strdup_if_not_null(key);
mysql->options.ssl_cert= strdup_if_not_null(cert);
mysql->options.ssl_ca= strdup_if_not_null(ca);
mysql->options.ssl_capath= strdup_if_not_null(capath);
mysql->options.ssl_cipher= strdup_if_not_null(cipher);
-#endif /* HAVE_OPENSSL */
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
DBUG_RETURN(0);
}
@@ -1668,7 +1794,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
NB! Errors are not reported until you do mysql_real_connect.
*/
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
static void
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
@@ -1676,14 +1802,14 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
struct st_VioSSLFd *ssl_fd= (struct st_VioSSLFd*) mysql->connector_fd;
DBUG_ENTER("mysql_ssl_free");
- my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.ssl_key);
+ my_free(mysql->options.ssl_cert);
+ my_free(mysql->options.ssl_ca);
+ my_free(mysql->options.ssl_capath);
+ my_free(mysql->options.ssl_cipher);
if (ssl_fd)
SSL_CTX_free(ssl_fd->ssl_context);
- my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->connector_fd);
mysql->options.ssl_key = 0;
mysql->options.ssl_cert = 0;
mysql->options.ssl_ca = 0;
@@ -1694,7 +1820,7 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
DBUG_VOID_RETURN;
}
-#endif /* HAVE_OPENSSL */
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
/*
Return the SSL cipher (if any) used for current
@@ -1710,10 +1836,10 @@ const char * STDCALL
mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
{
DBUG_ENTER("mysql_get_ssl_cipher");
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
if (mysql->net.vio && mysql->net.vio->ssl_arg)
DBUG_RETURN(SSL_get_cipher_name((SSL*)mysql->net.vio->ssl_arg));
-#endif /* HAVE_OPENSSL */
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
DBUG_RETURN(NULL);
}
@@ -1726,6 +1852,8 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
ssl_verify_server_cert()
vio pointer to a SSL connected vio
server_hostname name of the server that we connected to
+ errptr if we fail, we'll return (a pointer to a string
+ describing) the reason here
RETURN VALUES
0 Success
@@ -1733,9 +1861,9 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
*/
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
-static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
+static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const char **errptr)
{
SSL *ssl;
X509 *server_cert;
@@ -1746,19 +1874,19 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
if (!(ssl= (SSL*)vio->ssl_arg))
{
- DBUG_PRINT("error", ("No SSL pointer found"));
+ *errptr= "No SSL pointer found";
DBUG_RETURN(1);
}
if (!server_hostname)
{
- DBUG_PRINT("error", ("No server hostname supplied"));
+ *errptr= "No server hostname supplied";
DBUG_RETURN(1);
}
if (!(server_cert= SSL_get_peer_certificate(ssl)))
{
- DBUG_PRINT("error", ("Could not get server certificate"));
+ *errptr= "Could not get server certificate";
DBUG_RETURN(1);
}
@@ -1787,11 +1915,11 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
DBUG_RETURN(0);
}
}
- DBUG_PRINT("error", ("SSL certificate validation failure"));
+ *errptr= "SSL certificate validation failure";
DBUG_RETURN(1);
}
-#endif /* HAVE_OPENSSL */
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
/*
@@ -1829,52 +1957,299 @@ static MYSQL_METHODS client_methods=
#endif
};
+
+
+typedef enum my_cs_match_type_enum
+{
+ /* MySQL and OS charsets are fully compatible */
+ my_cs_exact,
+ /* MySQL charset is very close to OS charset */
+ my_cs_approx,
+ /*
+ MySQL knows this charset, but it is not supported as client character set.
+ */
+ my_cs_unsupp
+} my_cs_match_type;
+
+
+typedef struct str2str_st
+{
+ const char *os_name;
+ const char *my_name;
+ my_cs_match_type param;
+} MY_CSET_OS_NAME;
+
+const MY_CSET_OS_NAME charsets[]=
+{
+#ifdef __WIN__
+ {"cp437", "cp850", my_cs_approx},
+ {"cp850", "cp850", my_cs_exact},
+ {"cp852", "cp852", my_cs_exact},
+ {"cp858", "cp850", my_cs_approx},
+ {"cp866", "cp866", my_cs_exact},
+ {"cp874", "tis620", my_cs_approx},
+ {"cp932", "cp932", my_cs_exact},
+ {"cp936", "gbk", my_cs_approx},
+ {"cp949", "euckr", my_cs_approx},
+ {"cp950", "big5", my_cs_exact},
+ {"cp1200", "utf16le", my_cs_unsupp},
+ {"cp1201", "utf16", my_cs_unsupp},
+ {"cp1250", "cp1250", my_cs_exact},
+ {"cp1251", "cp1251", my_cs_exact},
+ {"cp1252", "latin1", my_cs_exact},
+ {"cp1253", "greek", my_cs_exact},
+ {"cp1254", "latin5", my_cs_exact},
+ {"cp1255", "hebrew", my_cs_approx},
+ {"cp1256", "cp1256", my_cs_exact},
+ {"cp1257", "cp1257", my_cs_exact},
+ {"cp10000", "macroman", my_cs_exact},
+ {"cp10001", "sjis", my_cs_approx},
+ {"cp10002", "big5", my_cs_approx},
+ {"cp10008", "gb2312", my_cs_approx},
+ {"cp10021", "tis620", my_cs_approx},
+ {"cp10029", "macce", my_cs_exact},
+ {"cp12001", "utf32", my_cs_unsupp},
+ {"cp20107", "swe7", my_cs_exact},
+ {"cp20127", "latin1", my_cs_approx},
+ {"cp20866", "koi8r", my_cs_exact},
+ {"cp20932", "ujis", my_cs_exact},
+ {"cp20936", "gb2312", my_cs_approx},
+ {"cp20949", "euckr", my_cs_approx},
+ {"cp21866", "koi8u", my_cs_exact},
+ {"cp28591", "latin1", my_cs_approx},
+ {"cp28592", "latin2", my_cs_exact},
+ {"cp28597", "greek", my_cs_exact},
+ {"cp28598", "hebrew", my_cs_exact},
+ {"cp28599", "latin5", my_cs_exact},
+ {"cp28603", "latin7", my_cs_exact},
+#ifdef UNCOMMENT_THIS_WHEN_WL_4579_IS_DONE
+ {"cp28605", "latin9", my_cs_exact},
+#endif
+ {"cp38598", "hebrew", my_cs_exact},
+ {"cp51932", "ujis", my_cs_exact},
+ {"cp51936", "gb2312", my_cs_exact},
+ {"cp51949", "euckr", my_cs_exact},
+ {"cp51950", "big5", my_cs_exact},
+#ifdef UNCOMMENT_THIS_WHEN_WL_WL_4024_IS_DONE
+ {"cp54936", "gb18030", my_cs_exact},
+#endif
+ {"cp65001", "utf8", my_cs_exact},
+
+#else /* not Windows */
+
+ {"646", "latin1", my_cs_approx}, /* Default on Solaris */
+ {"ANSI_X3.4-1968", "latin1", my_cs_approx},
+ {"ansi1251", "cp1251", my_cs_exact},
+ {"armscii8", "armscii8", my_cs_exact},
+ {"armscii-8", "armscii8", my_cs_exact},
+ {"ASCII", "latin1", my_cs_approx},
+ {"Big5", "big5", my_cs_exact},
+ {"cp1251", "cp1251", my_cs_exact},
+ {"cp1255", "hebrew", my_cs_approx},
+ {"CP866", "cp866", my_cs_exact},
+ {"eucCN", "gb2312", my_cs_exact},
+ {"euc-CN", "gb2312", my_cs_exact},
+ {"eucJP", "ujis", my_cs_exact},
+ {"euc-JP", "ujis", my_cs_exact},
+ {"eucKR", "euckr", my_cs_exact},
+ {"euc-KR", "euckr", my_cs_exact},
+#ifdef UNCOMMENT_THIS_WHEN_WL_WL_4024_IS_DONE
+ {"gb18030", "gb18030", my_cs_exact},
+#endif
+ {"gb2312", "gb2312", my_cs_exact},
+ {"gbk", "gbk", my_cs_exact},
+ {"georgianps", "geostd8", my_cs_exact},
+ {"georgian-ps", "geostd8", my_cs_exact},
+ {"IBM-1252", "cp1252", my_cs_exact},
+
+ {"iso88591", "latin1", my_cs_approx},
+ {"ISO_8859-1", "latin1", my_cs_approx},
+ {"ISO8859-1", "latin1", my_cs_approx},
+ {"ISO-8859-1", "latin1", my_cs_approx},
+
+ {"iso885913", "latin7", my_cs_exact},
+ {"ISO_8859-13", "latin7", my_cs_exact},
+ {"ISO8859-13", "latin7", my_cs_exact},
+ {"ISO-8859-13", "latin7", my_cs_exact},
+
+#ifdef UNCOMMENT_THIS_WHEN_WL_4579_IS_DONE
+ {"iso885915", "latin9", my_cs_exact},
+ {"ISO_8859-15", "latin9", my_cs_exact},
+ {"ISO8859-15", "latin9", my_cs_exact},
+ {"ISO-8859-15", "latin9", my_cs_exact},
+#endif
+
+ {"iso88592", "latin2", my_cs_exact},
+ {"ISO_8859-2", "latin2", my_cs_exact},
+ {"ISO8859-2", "latin2", my_cs_exact},
+ {"ISO-8859-2", "latin2", my_cs_exact},
+
+ {"iso88597", "greek", my_cs_exact},
+ {"ISO_8859-7", "greek", my_cs_exact},
+ {"ISO8859-7", "greek", my_cs_exact},
+ {"ISO-8859-7", "greek", my_cs_exact},
+
+ {"iso88598", "hebrew", my_cs_exact},
+ {"ISO_8859-8", "hebrew", my_cs_exact},
+ {"ISO8859-8", "hebrew", my_cs_exact},
+ {"ISO-8859-8", "hebrew", my_cs_exact},
+
+ {"iso88599", "latin5", my_cs_exact},
+ {"ISO_8859-9", "latin5", my_cs_exact},
+ {"ISO8859-9", "latin5", my_cs_exact},
+ {"ISO-8859-9", "latin5", my_cs_exact},
+
+ {"koi8r", "koi8r", my_cs_exact},
+ {"KOI8-R", "koi8r", my_cs_exact},
+ {"koi8u", "koi8u", my_cs_exact},
+ {"KOI8-U", "koi8u", my_cs_exact},
+
+ {"roman8", "hp8", my_cs_exact}, /* Default on HP UX */
+
+ {"Shift_JIS", "sjis", my_cs_exact},
+ {"SJIS", "sjis", my_cs_exact},
+ {"shiftjisx0213", "sjis", my_cs_exact},
+
+ {"tis620", "tis620", my_cs_exact},
+ {"tis-620", "tis620", my_cs_exact},
+
+ {"ujis", "ujis", my_cs_exact},
+
+ {"US-ASCII", "latin1", my_cs_approx},
+
+ {"utf8", "utf8", my_cs_exact},
+ {"utf-8", "utf8", my_cs_exact},
+#endif
+ {NULL, NULL, 0}
+};
+
+
+static const char *
+my_os_charset_to_mysql_charset(const char *csname)
+{
+ const MY_CSET_OS_NAME *csp;
+ for (csp= charsets; csp->os_name; csp++)
+ {
+ if (!my_strcasecmp(&my_charset_latin1, csp->os_name, csname))
+ {
+ switch (csp->param)
+ {
+ case my_cs_exact:
+ return csp->my_name;
+
+ case my_cs_approx:
+ /*
+ Maybe we should print a warning eventually:
+ character set correspondence is not exact.
+ */
+ return csp->my_name;
+
+ default:
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "OS character set '%s'"
+ " is not supported by MySQL client",
+ MYF(0), csp->my_name);
+ goto def;
+ }
+ }
+ }
+
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "Unknown OS character set '%s'.",
+ MYF(0), csname);
+
+def:
+ csname= MYSQL_DEFAULT_CHARSET_NAME;
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "Switching to the default character set '%s'.",
+ MYF(0), csname);
+ return csname;
+}
+
+
+#ifndef __WIN__
+#include <stdlib.h> /* for getenv() */
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#endif /* __WIN__ */
+
+
+static int
+mysql_autodetect_character_set(MYSQL *mysql)
+{
+ const char *csname= MYSQL_DEFAULT_CHARSET_NAME;
+
+#ifdef __WIN__
+ char cpbuf[64];
+ {
+ my_snprintf(cpbuf, sizeof(cpbuf), "cp%d", (int) GetConsoleCP());
+ csname= my_os_charset_to_mysql_charset(cpbuf);
+ }
+#elif defined(HAVE_SETLOCALE) && defined(HAVE_NL_LANGINFO)
+ {
+ if (setlocale(LC_CTYPE, "") && (csname= nl_langinfo(CODESET)))
+ csname= my_os_charset_to_mysql_charset(csname);
+ }
+#endif
+
+ my_free(mysql->options.charset_name);
+ if (!(mysql->options.charset_name= my_strdup(csname, MYF(MY_WME))))
+ return 1;
+ return 0;
+}
+
+
+static void
+mysql_set_character_set_with_default_collation(MYSQL *mysql)
+{
+ const char *save= charsets_dir;
+ if (mysql->options.charset_dir)
+ charsets_dir=mysql->options.charset_dir;
+
+ if ((mysql->charset= get_charset_by_csname(mysql->options.charset_name,
+ MY_CS_PRIMARY, MYF(MY_WME))))
+ {
+ /* Try to set compiled default collation when it's possible. */
+ CHARSET_INFO *collation;
+ if ((collation=
+ get_charset_by_name(MYSQL_DEFAULT_COLLATION_NAME, MYF(MY_WME))) &&
+ my_charset_same(mysql->charset, collation))
+ {
+ mysql->charset= collation;
+ }
+ else
+ {
+ /*
+ Default compiled collation not found, or is not applicable
+ to the requested character set.
+ Continue with the default collation of the character set.
+ */
+ }
+ }
+ charsets_dir= save;
+}
+
+
C_MODE_START
int mysql_init_character_set(MYSQL *mysql)
{
- const char *default_collation_name;
-
/* Set character set */
if (!mysql->options.charset_name)
{
- default_collation_name= MYSQL_DEFAULT_COLLATION_NAME;
if (!(mysql->options.charset_name=
my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
- return 1;
- }
- else
- default_collation_name= NULL;
-
- {
- const char *save= charsets_dir;
- if (mysql->options.charset_dir)
- charsets_dir=mysql->options.charset_dir;
- mysql->charset=get_charset_by_csname(mysql->options.charset_name,
- MY_CS_PRIMARY, MYF(MY_WME));
- if (mysql->charset && default_collation_name)
- {
- CHARSET_INFO *collation;
- if ((collation=
- get_charset_by_name(default_collation_name, MYF(MY_WME))))
- {
- if (!my_charset_same(mysql->charset, collation))
- {
- my_printf_error(ER_UNKNOWN_ERROR,
- "COLLATION %s is not valid for CHARACTER SET %s",
- MYF(0),
- default_collation_name, mysql->options.charset_name);
- mysql->charset= NULL;
- }
- else
- {
- mysql->charset= collation;
- }
- }
- else
- mysql->charset= NULL;
- }
- charsets_dir= save;
+ return 1;
}
+ else if (!strcmp(mysql->options.charset_name,
+ MYSQL_AUTODETECT_CHARSET_NAME) &&
+ mysql_autodetect_character_set(mysql))
+ return 1;
+
+ mysql_set_character_set_with_default_collation(mysql);
if (!mysql->charset)
{
@@ -1913,6 +2288,9 @@ static auth_plugin_t native_password_client_plugin=
"R.J.Silk, Sergei Golubchik",
"Native MySQL authentication",
{1, 0, 0},
+ "GPL",
+ NULL,
+ NULL,
NULL,
NULL,
native_password_auth_client
@@ -1926,6 +2304,9 @@ static auth_plugin_t old_password_client_plugin=
"R.J.Silk, Sergei Golubchik",
"Old MySQL-3.23 authentication",
{1, 0, 0},
+ "GPL",
+ NULL,
+ NULL,
NULL,
NULL,
old_password_auth_client
@@ -1938,8 +2319,6 @@ struct st_mysql_client_plugin *mysql_client_builtins[]=
0
};
-
-
/* this is a "superset" of MYSQL_PLUGIN_VIO, in C++ I use inheritance */
typedef struct {
int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
@@ -1947,15 +2326,15 @@ typedef struct {
void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
/* -= end of MYSQL_PLUGIN_VIO =- */
MYSQL *mysql;
- auth_plugin_t *plugin; /**< what plugin we're under */
+ auth_plugin_t *plugin; /**< what plugin we're under */
const char *db;
struct {
- uchar *pkt; /**< pointer into NET::buff */
+ uchar *pkt; /**< pointer into NET::buff */
uint pkt_len;
} cached_server_reply;
- uint packets_read, packets_written; /**< counters for send/received packets */
- my_bool mysql_change_user; /**< if it's mysql_change_user() */
- int last_read_packet_len; /**< the length of the last *read* packet */
+ int packets_read, packets_written; /**< counters for send/received packets */
+ int mysql_change_user; /**< if it's mysql_change_user() */
+ int last_read_packet_len; /**< the length of the last *read* packet */
} MCPVIO_EXT;
/**
@@ -1977,7 +2356,6 @@ typedef struct {
@retval 0 ok
@retval 1 error
*/
-
static int send_change_user_packet(MCPVIO_EXT *mpvio,
const uchar *data, int data_len)
{
@@ -2061,7 +2439,6 @@ error:
@retval 0 ok
@retval 1 error
*/
-
static int send_client_reply_packet(MCPVIO_EXT *mpvio,
const uchar *data, int data_len)
{
@@ -2119,7 +2496,9 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
/* Do the SSL layering. */
struct st_mysql_options *options= &mysql->options;
struct st_VioSSLFd *ssl_fd;
- char error_string[1024];
+ enum enum_ssl_init_error ssl_init_error;
+ const char *cert_error;
+ unsigned long ssl_error;
/*
Send mysql->client_flag, max_packet_size - unencrypted otherwise
@@ -2139,32 +2518,36 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
options->ssl_cert,
options->ssl_ca,
options->ssl_capath,
- options->ssl_cipher)))
+ options->ssl_cipher,
+ &ssl_init_error)))
{
- set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
+ set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
+ ER(CR_SSL_CONNECTION_ERROR), sslGetErrString(ssl_init_error));
goto error;
}
- mysql->connector_fd= (void*)ssl_fd;
+ mysql->connector_fd= (unsigned char *) ssl_fd;
/* Connect to the server */
DBUG_PRINT("info", ("IO layer change in progress..."));
if (sslconnect(ssl_fd, net->vio,
- (long) (mysql->options.connect_timeout),
- error_string))
- {
- set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR,
- unknown_sqlstate, "SSL error: %s",
- error_string[0] ? error_string :
- ER(CR_SSL_CONNECTION_ERROR));
+ (long) (mysql->options.connect_timeout), &ssl_error))
+ {
+ char buf[512];
+ ERR_error_string_n(ssl_error, buf, 512);
+ buf[511]= 0;
+ set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
+ ER(CR_SSL_CONNECTION_ERROR),
+ buf);
goto error;
}
DBUG_PRINT("info", ("IO layer change done!"));
/* Verify server cert */
if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
- ssl_verify_server_cert(net->vio, mysql->host))
+ ssl_verify_server_cert(net->vio, mysql->host, &cert_error))
{
- set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
+ set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
+ ER(CR_SSL_CONNECTION_ERROR), cert_error);
goto error;
}
}
@@ -2237,7 +2620,6 @@ error:
This function is called by a client authentication plugin, when it wants
to read data from the server.
*/
-
static int client_mpvio_read_packet(struct st_plugin_vio *mpv, uchar **buf)
{
MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;
@@ -2300,7 +2682,6 @@ static int client_mpvio_read_packet(struct st_plugin_vio *mpv, uchar **buf)
It transparently wraps the data into a change user or authentication
handshake packet, if neccessary.
*/
-
static int client_mpvio_write_packet(struct st_plugin_vio *mpv,
const uchar *pkt, int pkt_len)
{
@@ -2336,7 +2717,6 @@ static int client_mpvio_write_packet(struct st_plugin_vio *mpv,
fills MYSQL_PLUGIN_VIO_INFO structure with the information about the
connection
*/
-
void mpvio_info(Vio *vio, MYSQL_PLUGIN_VIO_INFO *info)
{
bzero(info, sizeof(*info));
@@ -2367,7 +2747,9 @@ void mpvio_info(Vio *vio, MYSQL_PLUGIN_VIO_INFO *info)
return;
case VIO_TYPE_SHARED_MEMORY:
info->protocol= MYSQL_VIO_MEMORY;
+#ifdef HAVE_SMEM
info->handle= vio->handle_file_map; /* or what ? */
+#endif
return;
#endif
default: DBUG_ASSERT(0);
@@ -2399,7 +2781,6 @@ static void client_mpvio_info(MYSQL_PLUGIN_VIO *vio,
@retval 0 ok
@retval 1 error
*/
-
int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
const char *data_plugin, const char *db)
{
@@ -2409,6 +2790,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
ulong pkt_length;
int res;
+ DBUG_ENTER ("run_plugin_auth");
/* determine the default/initial plugin to use */
if (mysql->options.extension && mysql->options.extension->default_auth &&
mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
@@ -2416,7 +2798,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
auth_plugin_name= mysql->options.extension->default_auth;
if (!(auth_plugin= (auth_plugin_t*) mysql_client_find_plugin(mysql,
auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
- return 1; /* oops, not found */
+ DBUG_RETURN (1); /* oops, not found */
}
else
{
@@ -2425,6 +2807,8 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
auth_plugin_name= auth_plugin->name;
}
+ DBUG_PRINT ("info", ("using plugin %s", auth_plugin_name));
+
mysql->net.last_errno= 0; /* just in case */
if (data_plugin && strcmp(data_plugin, auth_plugin_name))
@@ -2446,6 +2830,11 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
mpvio.plugin= auth_plugin;
res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
+ DBUG_PRINT ("info", ("authenticate_user returned %s",
+ res == CR_OK ? "CR_OK" :
+ res == CR_ERROR ? "CR_ERROR" :
+ res == CR_OK_HANDSHAKE_COMPLETE ?
+ "CR_OK_HANDSHAKE_COMPLETE" : "error"));
compile_time_assert(CR_OK == -1);
compile_time_assert(CR_ERROR == 0);
@@ -2456,12 +2845,13 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
unless the error code is CR_ERROR and mysql->net.last_errno
is already set (the plugin has done it)
*/
+ DBUG_PRINT ("info", ("res=%d", res));
if (res > CR_ERROR)
set_mysql_error(mysql, res, unknown_sqlstate);
else
if (!mysql->net.last_errno)
set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
- return 1;
+ DBUG_RETURN (1);
}
/* read the OK packet (or use the cached value in mysql->net.read_pos */
@@ -2470,6 +2860,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
else /* res == CR_OK_HANDSHAKE_COMPLETE */
pkt_length= mpvio.last_read_packet_len;
+ DBUG_PRINT ("info", ("OK packet length=%lu", pkt_length));
if (pkt_length == packet_error)
{
if (mysql->net.last_errno == CR_SERVER_LOST)
@@ -2477,7 +2868,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
ER(CR_SERVER_LOST_EXTENDED),
"reading authorization packet",
errno);
- return 1;
+ DBUG_RETURN (1);
}
if (mysql->net.read_pos[0] == 254)
@@ -2486,6 +2877,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
if (pkt_length == 1)
{
/* old "use short scramble" packet */
+ DBUG_PRINT ("info", ("old use short scramble packet from server"));
auth_plugin_name= old_password_plugin_name;
mpvio.cached_server_reply.pkt= (uchar*)mysql->scramble;
mpvio.cached_server_reply.pkt_len= SCRAMBLE_LENGTH + 1;
@@ -2498,15 +2890,22 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
len= strlen(auth_plugin_name); /* safe as my_net_read always appends \0 */
mpvio.cached_server_reply.pkt_len= pkt_length - len - 2;
mpvio.cached_server_reply.pkt= mysql->net.read_pos + len + 2;
+ DBUG_PRINT ("info", ("change plugin packet from server for plugin %s",
+ auth_plugin_name));
}
if (!(auth_plugin= (auth_plugin_t *) mysql_client_find_plugin(mysql,
auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
- return 1;
+ DBUG_RETURN (1);
mpvio.plugin= auth_plugin;
res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
+ DBUG_PRINT ("info", ("second authenticate_user returned %s",
+ res == CR_OK ? "CR_OK" :
+ res == CR_ERROR ? "CR_ERROR" :
+ res == CR_OK_HANDSHAKE_COMPLETE ?
+ "CR_OK_HANDSHAKE_COMPLETE" : "error"));
if (res > CR_OK)
{
if (res > CR_ERROR)
@@ -2514,7 +2913,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
else
if (!mysql->net.last_errno)
set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
- return 1;
+ DBUG_RETURN (1);
}
if (res != CR_OK_HANDSHAKE_COMPLETE)
@@ -2527,7 +2926,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
ER(CR_SERVER_LOST_EXTENDED),
"reading final connect information",
errno);
- return 1;
+ DBUG_RETURN (1);
}
}
}
@@ -2535,7 +2934,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
net->read_pos[0] should always be 0 here if the server implements
the protocol correctly
*/
- return mysql->net.read_pos[0] != 0;
+ DBUG_RETURN (mysql->net.read_pos[0] != 0);
}
@@ -2545,13 +2944,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
uint port, const char *unix_socket,ulong client_flag)
{
char buff[NAME_LEN+USERNAME_LENGTH+100];
- int scramble_data_len, pkt_scramble_len;
- char *end, *host_info=0, *server_version_end, *pkt_end;
+ int scramble_data_len, pkt_scramble_len= 0;
+ char *end,*host_info= 0, *server_version_end, *pkt_end;
char *scramble_data;
const char *scramble_plugin;
- my_socket sock;
- in_addr_t ip_addr;
- struct sockaddr_in sock_addr;
ulong pkt_length;
NET *net= &mysql->net;
#ifdef MYSQL_SERVER
@@ -2564,17 +2960,21 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
#ifdef HAVE_SYS_UN_H
struct sockaddr_un UNIXaddr;
#endif
- init_sigpipe_variables
DBUG_ENTER("mysql_real_connect");
LINT_INIT(pkt_scramble_len);
- DBUG_PRINT("enter",("host: %s db: %s user: %s",
+ DBUG_PRINT("enter",("host: %s db: %s user: %s (client)",
host ? host : "(Null)",
db ? db : "(Null)",
user ? user : "(Null)"));
- /* Don't give sigpipe errors if the client doesn't want them */
- set_sigpipe(mysql);
+ /* Test whether we're already connected */
+ if (net->vio)
+ {
+ set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate);
+ DBUG_RETURN(0);
+ }
+
mysql->methods= &client_methods;
net->vio = 0; /* If something goes wrong */
mysql->client_flag=0; /* For handshake */
@@ -2586,8 +2986,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
(mysql->options.my_cnf_file ?
mysql->options.my_cnf_file : "my"),
mysql->options.my_cnf_group);
- my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.my_cnf_file);
+ my_free(mysql->options.my_cnf_group);
mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
}
@@ -2618,6 +3018,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
unix_socket=mysql->options.unix_socket;
mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
+ DBUG_PRINT("info", ("Connecting"));
/*
Part 0: Grab a socket and connect it to the server
@@ -2628,6 +3029,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
(!host || !strcmp(host,LOCAL_HOST)) &&
mysql->options.shared_memory_base_name)
{
+ DBUG_PRINT("info", ("Using shared memory"));
if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) ==
INVALID_HANDLE_VALUE)
{
@@ -2650,7 +3052,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
else
{
mysql->options.protocol=MYSQL_PROTOCOL_MEMORY;
- sock=0;
unix_socket = 0;
host=mysql->options.shared_memory_base_name;
my_snprintf(host_info=buff, sizeof(buff)-1,
@@ -2665,12 +3066,9 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
(unix_socket || mysql_unix_port) &&
(!host || !strcmp(host,LOCAL_HOST)))
{
- host=LOCAL_HOST;
- if (!unix_socket)
- unix_socket=mysql_unix_port;
- host_info=(char*) ER(CR_LOCALHOST_CONNECTION);
- DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket));
- if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR)
+ my_socket sock= socket(AF_UNIX, SOCK_STREAM, 0);
+ DBUG_PRINT("info", ("Using socket"));
+ if (sock == SOCKET_ERROR)
{
set_mysql_extended_error(mysql, CR_SOCKET_CREATE_ERROR,
unknown_sqlstate,
@@ -2678,12 +3076,28 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
socket_errno);
goto error;
}
+
net->vio= vio_new(sock, VIO_TYPE_SOCKET,
VIO_LOCALHOST | VIO_BUFFERED_READ);
- bzero((char*) &UNIXaddr,sizeof(UNIXaddr));
- UNIXaddr.sun_family = AF_UNIX;
+ if (!net->vio)
+ {
+ DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
+ set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
+ closesocket(sock);
+ goto error;
+ }
+
+ host= LOCAL_HOST;
+ if (!unix_socket)
+ unix_socket= mysql_unix_port;
+ host_info= (char*) ER(CR_LOCALHOST_CONNECTION);
+ DBUG_PRINT("info", ("Using UNIX sock '%s'", unix_socket));
+
+ bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
+ UNIXaddr.sun_family= AF_UNIX;
strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1);
- if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
+
+ if (my_connect(sock, (struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
mysql->options.connect_timeout))
{
DBUG_PRINT("error",("Got error %d on connect to local server",
@@ -2692,6 +3106,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
unknown_sqlstate,
ER(CR_CONNECTION_ERROR),
unix_socket, socket_errno);
+ vio_delete(net->vio);
+ net->vio= 0;
goto error;
}
mysql->options.protocol=MYSQL_PROTOCOL_SOCKET;
@@ -2702,7 +3118,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
(host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
(! have_tcpip && (unix_socket || !host && is_NT()))))
{
- sock=0;
if ((hPipe= create_named_pipe(mysql, mysql->options.connect_timeout,
(char**) &host, (char**) &unix_socket)) ==
INVALID_HANDLE_VALUE)
@@ -2726,93 +3141,130 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
}
}
#endif
+ DBUG_PRINT("info", ("net->vio: %p protocol: %d",
+ net->vio, mysql->options.protocol));
if (!net->vio &&
(!mysql->options.protocol ||
mysql->options.protocol == MYSQL_PROTOCOL_TCP))
{
- int status= -1;
+ struct addrinfo *res_lst, hints, *t_res;
+ int gai_errno;
+ char port_buf[NI_MAXSERV];
+ my_socket sock= SOCKET_ERROR;
+ int saved_error= 0, status= -1;
+
unix_socket=0; /* This is not used */
+
if (!port)
- port=mysql_port;
+ port= mysql_port;
+
if (!host)
- host=LOCAL_HOST;
- my_snprintf(host_info=buff,sizeof(buff)-1,ER(CR_TCP_CONNECTION),host);
- DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port));
+ host= LOCAL_HOST;
+
+ my_snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
+ DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host, port));
#ifdef MYSQL_SERVER
thr_alarm_init(&alarmed);
thr_alarm(&alarmed, mysql->options.connect_timeout, &alarm_buff);
#endif
- /* _WIN64 ; Assume that the (int) range is enough for socket() */
- sock = (my_socket) socket(AF_INET,SOCK_STREAM,0);
+
+ DBUG_PRINT("info",("IP '%s'", "client"));
+
#ifdef MYSQL_SERVER
thr_end_alarm(&alarmed);
#endif
- if (sock == SOCKET_ERROR)
- {
- set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
- ER(CR_IPSOCK_ERROR), socket_errno);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype= SOCK_STREAM;
+ hints.ai_protocol= IPPROTO_TCP;
+ hints.ai_family= AF_UNSPEC;
+
+ DBUG_PRINT("info",("IPV6 getaddrinfo %s", host));
+ my_snprintf(port_buf, NI_MAXSERV, "%d", port);
+ gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
+
+ if (gai_errno != 0)
+ {
+ /*
+ For DBUG we are keeping the right message but for client we default to
+ historical error message.
+ */
+ DBUG_PRINT("info",("IPV6 getaddrinfo error %d", gai_errno));
+ set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate,
+ ER(CR_UNKNOWN_HOST), host, errno);
+
goto error;
}
- net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
- bzero((char*) &sock_addr,sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_port = (ushort) htons((ushort) port);
/*
- The server name may be a host name or IP address
+ A hostname might map to multiple IP addresses (IPv4/IPv6). Go over the
+ list of IP addresses until a successful connection can be established.
*/
-
- if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE)
- {
- memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr));
- status= my_connect(sock, (struct sockaddr *) &sock_addr,
- sizeof(sock_addr), mysql->options.connect_timeout);
- }
- else
+ DBUG_PRINT("info", ("Try connect on all addresses for host."));
+ for (t_res= res_lst; t_res; t_res= t_res->ai_next)
{
- int i, tmp_errno;
- struct hostent tmp_hostent,*hp;
- char buff2[GETHOSTBYNAME_BUFF_SIZE];
- hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2),
- &tmp_errno);
+ DBUG_PRINT("info", ("Create socket, family: %d type: %d proto: %d",
+ t_res->ai_family, t_res->ai_socktype,
+ t_res->ai_protocol));
+ sock= socket(t_res->ai_family, t_res->ai_socktype, t_res->ai_protocol);
+ if (sock == SOCKET_ERROR)
+ {
+ saved_error= socket_errno;
+ continue;
+ }
+ DBUG_PRINT("info", ("Connect socket"));
+ status= my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
+ mysql->options.connect_timeout);
/*
- Don't attempt to connect to non IPv4 addresses as the client could
- end up sending information to a unknown server. For example, a IPv6
- address might be returned from gethostbyname depending on options
- set via the RES_OPTIONS environment variable.
+ Here we rely on my_connect() to return success only if the
+ connect attempt was really successful. Otherwise we would stop
+ trying another address, believing we were successful.
*/
- if (!hp || (hp->h_addrtype != AF_INET))
- {
- my_gethostbyname_r_free();
- set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate,
- ER(CR_UNKNOWN_HOST), host, tmp_errno);
- goto error;
- }
+ if (!status)
+ break;
- for (i= 0; status && hp->h_addr_list[i]; i++)
- {
- IF_DBUG(char ipaddr[18];)
- memcpy(&sock_addr.sin_addr, hp->h_addr_list[i],
- min(sizeof(sock_addr.sin_addr), (size_t) hp->h_length));
- DBUG_PRINT("info",("Trying %s...",
- (my_inet_ntoa(sock_addr.sin_addr, ipaddr), ipaddr)));
- status= my_connect(sock, (struct sockaddr *) &sock_addr,
- sizeof(sock_addr), mysql->options.connect_timeout);
- }
+ /*
+ Save value as socket errno might be overwritten due to
+ calling a socket function below.
+ */
+ saved_error= socket_errno;
- my_gethostbyname_r_free();
+ DBUG_PRINT("info", ("No success, close socket, try next address."));
+ closesocket(sock);
+ }
+ DBUG_PRINT("info",
+ ("End of connect attempts, sock: %d status: %d error: %d",
+ sock, status, saved_error));
+
+ freeaddrinfo(res_lst);
+
+ if (sock == SOCKET_ERROR)
+ {
+ set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
+ ER(CR_IPSOCK_ERROR), saved_error);
+ goto error;
}
if (status)
{
- DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,
- host));
+ DBUG_PRINT("error",("Got error %d on connect to '%s'", saved_error, host));
set_mysql_extended_error(mysql, CR_CONN_HOST_ERROR, unknown_sqlstate,
- ER(CR_CONN_HOST_ERROR), host, socket_errno);
+ ER(CR_CONN_HOST_ERROR), host, saved_error);
+ goto error;
+ }
+
+ net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
+ if (! net->vio )
+ {
+ DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
+ set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
+ closesocket(sock);
goto error;
}
}
+
+ DBUG_PRINT("info", ("net->vio: %p", net->vio));
if (!net->vio)
{
DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol));
@@ -2855,6 +3307,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
/*
Part 1: Connection established, read and parse first packet
*/
+ DBUG_PRINT("info", ("Read first packet."));
if ((pkt_length=cli_safe_read(mysql)) == packet_error)
{
@@ -3026,17 +3479,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
}
#endif
-#ifndef TO_BE_DELETED
- if (mysql->options.rpl_probe && mysql_rpl_probe(mysql))
- goto error;
-#endif
-
DBUG_PRINT("exit", ("Mysql handler: 0x%lx", (long) mysql));
- reset_sigpipe(mysql);
DBUG_RETURN(mysql);
error:
- reset_sigpipe(mysql);
DBUG_PRINT("error",("message: %u/%s (%s)",
net->last_errno,
net->sqlstate,
@@ -3052,28 +3498,6 @@ error:
}
-/* needed when we move MYSQL structure to a different address */
-
-#ifndef TO_BE_DELETED
-static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql)
-{
- MYSQL *tmp, *tmp_prev;
- if (mysql->master == old_mysql)
- mysql->master= mysql;
- if (mysql->last_used_con == old_mysql)
- mysql->last_used_con= mysql;
- if (mysql->last_used_slave == old_mysql)
- mysql->last_used_slave= mysql;
- for (tmp_prev = mysql, tmp = mysql->next_slave;
- tmp != old_mysql;tmp = tmp->next_slave)
- {
- tmp_prev= tmp;
- }
- tmp_prev->next_slave= mysql;
-}
-#endif
-
-
my_bool mysql_reconnect(MYSQL *mysql)
{
MYSQL tmp_mysql;
@@ -3092,8 +3516,7 @@ my_bool mysql_reconnect(MYSQL *mysql)
mysql_init(&tmp_mysql);
tmp_mysql.options= mysql->options;
tmp_mysql.options.my_cnf_file= tmp_mysql.options.my_cnf_group= 0;
- tmp_mysql.rpl_pivot= mysql->rpl_pivot;
-
+
if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
mysql->db, mysql->port, mysql->unix_socket,
mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
@@ -3127,7 +3550,6 @@ my_bool mysql_reconnect(MYSQL *mysql)
mysql->free_me=0;
mysql_close(mysql);
*mysql=tmp_mysql;
- mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */
net_clear(&mysql->net, 1);
mysql->affected_rows= ~(my_ulonglong) 0;
DBUG_RETURN(0);
@@ -3148,7 +3570,7 @@ mysql_select_db(MYSQL *mysql, const char *db)
if ((error=simple_command(mysql,COM_INIT_DB, (const uchar*) db,
(ulong) strlen(db),0)))
DBUG_RETURN(error);
- my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->db);
mysql->db=my_strdup(db,MYF(MY_WME));
DBUG_RETURN(0);
}
@@ -3163,38 +3585,38 @@ static void mysql_close_free_options(MYSQL *mysql)
{
DBUG_ENTER("mysql_close_free_options");
- my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.user);
+ my_free(mysql->options.host);
+ my_free(mysql->options.password);
+ my_free(mysql->options.unix_socket);
+ my_free(mysql->options.db);
+ my_free(mysql->options.my_cnf_file);
+ my_free(mysql->options.my_cnf_group);
+ my_free(mysql->options.charset_dir);
+ my_free(mysql->options.charset_name);
+ my_free(mysql->options.client_ip);
if (mysql->options.init_commands)
{
DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
char **ptr= (char**)init_commands->buffer;
char **end= ptr + init_commands->elements;
for (; ptr<end; ptr++)
- my_free(*ptr,MYF(MY_WME));
+ my_free(*ptr);
delete_dynamic(init_commands);
- my_free((char*)init_commands,MYF(MY_WME));
+ my_free(init_commands);
}
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
mysql_ssl_free(mysql);
-#endif /* HAVE_OPENSSL */
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
#ifdef HAVE_SMEM
if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
- my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.shared_memory_base_name);
#endif /* HAVE_SMEM */
if (mysql->options.extension)
{
- my_free(mysql->options.extension->plugin_dir,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.extension->default_auth,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.extension,MYF(0));
+ my_free(mysql->options.extension->plugin_dir);
+ my_free(mysql->options.extension->default_auth);
+ my_free(mysql->options.extension);
}
bzero((char*) &mysql->options,sizeof(mysql->options));
DBUG_VOID_RETURN;
@@ -3203,12 +3625,12 @@ static void mysql_close_free_options(MYSQL *mysql)
static void mysql_close_free(MYSQL *mysql)
{
- my_free((uchar*) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->host_info);
+ my_free(mysql->user);
+ my_free(mysql->passwd);
+ my_free(mysql->db);
#if defined(EMBEDDED_LIBRARY) || MYSQL_VERSION_ID >= 50100
- my_free(mysql->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->info_buffer);
mysql->info_buffer= 0;
#endif
/* Clear pointers for better safety */
@@ -3320,26 +3742,6 @@ void STDCALL mysql_close(MYSQL *mysql)
mysql_close_free_options(mysql);
mysql_close_free(mysql);
mysql_detach_stmt_list(&mysql->stmts, "mysql_close");
-#ifndef TO_BE_DELETED
- /* free/close slave list */
- if (mysql->rpl_pivot)
- {
- MYSQL* tmp;
- for (tmp = mysql->next_slave; tmp != mysql; )
- {
- /* trick to avoid following freed pointer */
- MYSQL* tmp1 = tmp->next_slave;
- mysql_close(tmp);
- tmp = tmp1;
- }
- mysql->rpl_pivot=0;
- }
-#endif
- if (mysql != mysql->master)
- {
- mysql_close(mysql->master);
- mysql->master= 0;
- }
#ifndef MYSQL_SERVER
if (mysql->thd)
{
@@ -3348,7 +3750,7 @@ void STDCALL mysql_close(MYSQL *mysql)
}
#endif
if (mysql->free_me)
- my_free((uchar*) mysql,MYF(0));
+ my_free(mysql);
}
DBUG_VOID_RETURN;
}
@@ -3362,12 +3764,6 @@ static my_bool cli_read_query_result(MYSQL *mysql)
ulong length;
DBUG_ENTER("cli_read_query_result");
- /*
- Read from the connection which we actually used, which
- could differ from the original connection if we have slaves
- */
- mysql = mysql->last_used_con;
-
if ((length = cli_safe_read(mysql)) == packet_error)
DBUG_RETURN(1);
free_old_query(mysql); /* Free old result */
@@ -3442,23 +3838,6 @@ int STDCALL
mysql_send_query(MYSQL* mysql, const char* query, ulong length)
{
DBUG_ENTER("mysql_send_query");
- DBUG_PRINT("enter",("rpl_parse: %d rpl_pivot: %d",
- mysql->options.rpl_parse, mysql->rpl_pivot));
-#ifndef TO_BE_DELETED
- if (mysql->options.rpl_parse && mysql->rpl_pivot)
- {
- switch (mysql_rpl_query_type(query, length)) {
- case MYSQL_RPL_MASTER:
- DBUG_RETURN(mysql_master_send_query(mysql, query, length));
- case MYSQL_RPL_SLAVE:
- DBUG_RETURN(mysql_slave_send_query(mysql, query, length));
- case MYSQL_RPL_ADMIN:
- break; /* fall through */
- }
- }
- mysql->last_used_con = mysql;
-#endif
-
DBUG_RETURN(simple_command(mysql, COM_QUERY, (uchar*) query, length, 1));
}
@@ -3485,8 +3864,7 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
{
MYSQL_RES *result;
DBUG_ENTER("mysql_store_result");
- /* read from the actually used connection */
- mysql = mysql->last_used_con;
+
if (!mysql->fields)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
@@ -3509,7 +3887,7 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
if (!(result->data=
(*mysql->methods->read_rows)(mysql,mysql->fields,mysql->field_count)))
{
- my_free((uchar*) result,MYF(0));
+ my_free(result);
DBUG_RETURN(0);
}
mysql->affected_rows= result->row_count= result->data->rows;
@@ -3541,8 +3919,6 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql)
MYSQL_RES *result;
DBUG_ENTER("cli_use_result");
- mysql = mysql->last_used_con;
-
if (!mysql->fields)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
@@ -3559,7 +3935,7 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql)
if (!(result->row=(MYSQL_ROW)
my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME))))
{ /* Ptrs: to one row */
- my_free((uchar*) result,MYF(0));
+ my_free(result);
DBUG_RETURN(0);
}
result->fields= mysql->fields;
@@ -3651,7 +4027,7 @@ mysql_fetch_lengths(MYSQL_RES *res)
int STDCALL
mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
{
- DBUG_ENTER("mysql_option");
+ DBUG_ENTER("mysql_options");
DBUG_PRINT("enter",("option: %d",(int) option));
switch (option) {
case MYSQL_OPT_CONNECT_TIMEOUT:
@@ -3680,19 +4056,19 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
add_init_command(&mysql->options,arg);
break;
case MYSQL_READ_DEFAULT_FILE:
- my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.my_cnf_file);
mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
break;
case MYSQL_READ_DEFAULT_GROUP:
- my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.my_cnf_group);
mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
break;
case MYSQL_SET_CHARSET_DIR:
- my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.charset_dir);
mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME));
break;
case MYSQL_SET_CHARSET_NAME:
- my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.charset_name);
mysql->options.charset_name=my_strdup(arg,MYF(MY_WME));
break;
case MYSQL_OPT_PROTOCOL:
@@ -3701,7 +4077,7 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
case MYSQL_SHARED_MEMORY_BASE_NAME:
#ifdef HAVE_SMEM
if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
- my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.shared_memory_base_name);
mysql->options.shared_memory_base_name=my_strdup(arg,MYF(MY_WME));
#endif
break;
@@ -3729,10 +4105,10 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
mysql->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
break;
case MYSQL_PLUGIN_DIR:
- extension_set_string(&mysql->options, plugin_dir, arg);
+ EXTENSION_SET_STRING(&mysql->options, plugin_dir, arg);
break;
case MYSQL_DEFAULT_AUTH:
- extension_set_string(&mysql->options, default_auth, arg);
+ EXTENSION_SET_STRING(&mysql->options, default_auth, arg);
break;
case MYSQL_PROGRESS_CALLBACK:
if (!mysql->options.extension)
@@ -3850,17 +4226,18 @@ int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
return mysql->net.last_errno;
}
-
/**
client authentication plugin that does native MySQL authentication
using a 20-byte (4.1+) scramble
*/
-
static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
int pkt_len;
uchar *pkt;
+ DBUG_ENTER("native_password_auth_client");
+
+
if (((MCPVIO_EXT *)vio)->mysql_change_user)
{
/*
@@ -3874,10 +4251,10 @@ static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
/* read the scramble */
if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
- return CR_ERROR;
+ DBUG_RETURN(CR_ERROR);
if (pkt_len != SCRAMBLE_LENGTH + 1)
- return CR_SERVER_HANDSHAKE_ERR;
+ DBUG_RETURN(CR_SERVER_HANDSHAKE_ERR);
/* save it in MYSQL */
memcpy(mysql->scramble, pkt, SCRAMBLE_LENGTH);
@@ -3887,28 +4264,32 @@ static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
if (mysql->passwd[0])
{
char scrambled[SCRAMBLE_LENGTH + 1];
+ DBUG_PRINT("info", ("sending scramble"));
scramble(scrambled, (char*)pkt, mysql->passwd);
if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH))
- return CR_ERROR;
+ DBUG_RETURN(CR_ERROR);
}
else
+ {
+ DBUG_PRINT("info", ("no password"));
if (vio->write_packet(vio, 0, 0)) /* no password */
- return CR_ERROR;
+ DBUG_RETURN(CR_ERROR);
+ }
- return CR_OK;
+ DBUG_RETURN(CR_OK);
}
-
/**
client authentication plugin that does old MySQL authentication
using an 8-byte (4.0-) scramble
*/
-
static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
uchar *pkt;
int pkt_len;
+ DBUG_ENTER("old_password_auth_client");
+
if (((MCPVIO_EXT *)vio)->mysql_change_user)
{
/*
@@ -3922,14 +4303,14 @@ static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
/* read the scramble */
if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
- return CR_ERROR;
+ DBUG_RETURN(CR_ERROR);
if (pkt_len != SCRAMBLE_LENGTH_323 + 1 &&
pkt_len != SCRAMBLE_LENGTH + 1)
- return CR_SERVER_HANDSHAKE_ERR;
+ DBUG_RETURN(CR_SERVER_HANDSHAKE_ERR);
/* save it in MYSQL */
- memcpy(mysql->scramble, pkt, pkt_len);
+ memmove(mysql->scramble, pkt, pkt_len);
mysql->scramble[pkt_len] = 0;
}
@@ -3938,12 +4319,12 @@ static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
char scrambled[SCRAMBLE_LENGTH_323 + 1];
scramble_323(scrambled, (char*)pkt, mysql->passwd);
if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH_323 + 1))
- return CR_ERROR;
+ DBUG_RETURN(CR_ERROR);
}
else
if (vio->write_packet(vio, 0, 0)) /* no password */
- return CR_ERROR;
+ DBUG_RETURN(CR_ERROR);
- return CR_OK;
+ DBUG_RETURN(CR_OK);
}
diff --git a/sql-common/client_plugin.c b/sql-common/client_plugin.c
index 9a90e3c93fd..f31ddb22a6a 100644
--- a/sql-common/client_plugin.c
+++ b/sql-common/client_plugin.c
@@ -1,4 +1,5 @@
/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+ Copyright (c) 2010, 2011, Oracle and/or its affiliates.
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
@@ -11,7 +12,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
@@ -36,11 +37,7 @@
#include "mysql.h"
#include <my_sys.h>
#include <m_string.h>
-#ifdef THREAD
#include <my_pthread.h>
-#else
-#include <my_no_pthread.h>
-#endif
#include <sql_common.h>
#include "errmsg.h"
@@ -73,22 +70,21 @@ static uint plugin_version[MYSQL_CLIENT_MAX_PLUGINS]=
loading the same plugin twice in parallel.
*/
struct st_client_plugin_int *plugin_list[MYSQL_CLIENT_MAX_PLUGINS];
-#ifdef THREAD
static pthread_mutex_t LOCK_load_client_plugin;
-#endif
static int is_not_initialized(MYSQL *mysql, const char *name)
{
+ DBUG_ENTER("is_not_initialized");
+
if (initialized)
- return 0;
+ DBUG_RETURN(0);
set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
unknown_sqlstate, ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
name, "not initialized");
- return 1;
+ DBUG_RETURN(1);
}
-
/**
finds a plugin in the list
@@ -99,25 +95,25 @@ static int is_not_initialized(MYSQL *mysql, const char *name)
@retval a pointer to a found plugin or 0
*/
-
-static struct st_mysql_client_plugin *find_plugin(const char *name, int type)
+static struct st_mysql_client_plugin *
+find_plugin(const char *name, int type)
{
struct st_client_plugin_int *p;
+ DBUG_ENTER("find_plugin");
DBUG_ASSERT(initialized);
DBUG_ASSERT(type >= 0 && type < MYSQL_CLIENT_MAX_PLUGINS);
if (type < 0 || type >= MYSQL_CLIENT_MAX_PLUGINS)
- return 0;
+ DBUG_RETURN(0);
for (p= plugin_list[type]; p; p= p->next)
{
if (strcmp(p->plugin->name, name) == 0)
- return p->plugin;
+ DBUG_RETURN(p->plugin);
}
- return NULL;
+ DBUG_RETURN(NULL);
}
-
/**
verifies the plugin and adds it to the list
@@ -130,7 +126,6 @@ static struct st_mysql_client_plugin *find_plugin(const char *name, int type)
@retval a pointer to an installed plugin or 0
*/
-
static struct st_mysql_client_plugin *
add_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin, void *dlhandle,
int argc, va_list args)
@@ -138,6 +133,7 @@ add_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin, void *dlhandle,
const char *errmsg;
struct st_client_plugin_int plugin_int, *p;
char errbuf[1024];
+ DBUG_ENTER("add_plugin");
DBUG_ASSERT(initialized);
@@ -178,22 +174,22 @@ add_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin, void *dlhandle,
p->next= plugin_list[plugin->type];
plugin_list[plugin->type]= p;
+ net_clear_error(&mysql->net);
- return plugin;
+ DBUG_RETURN(plugin);
err2:
if (plugin->deinit)
plugin->deinit();
err1:
- if (dlhandle)
- (void)dlclose(dlhandle);
set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
ER(CR_AUTH_PLUGIN_CANNOT_LOAD), plugin->name,
errmsg);
- return NULL;
+ if (dlhandle)
+ (void)dlclose(dlhandle);
+ DBUG_RETURN(NULL);
}
-
/**
Loads plugins which are specified in the environment variable
LIBMYSQL_PLUGINS.
@@ -209,14 +205,14 @@ err1:
or
LIBMYSQL_PLUGINS="plugin1=int:param1,str:param2;plugin2;..."
*/
-
static void load_env_plugins(MYSQL *mysql)
{
char *plugs, *free_env, *s= getenv("LIBMYSQL_PLUGINS");
+ DBUG_ENTER("load_env_plugins");
/* no plugins to load */
if (!s)
- return;
+ DBUG_VOID_RETURN;
free_env= plugs= my_strdup(s, MYF(MY_WME));
@@ -227,7 +223,8 @@ static void load_env_plugins(MYSQL *mysql)
plugs= s + 1;
} while (s);
- my_free(free_env, MYF(0));
+ my_free(free_env);
+ DBUG_VOID_RETURN;
}
/********** extern functions to be used by libmysql *********************/
@@ -240,16 +237,16 @@ static void load_env_plugins(MYSQL *mysql)
@retval 0 successful
@retval != 0 error occured
*/
-
int mysql_client_plugin_init()
{
MYSQL mysql;
struct st_mysql_client_plugin **builtin;
va_list unused;
+ DBUG_ENTER("mysql_client_plugin_init");
LINT_INIT_STRUCT(unused);
if (initialized)
- return 0;
+ DBUG_RETURN(0);
bzero(&mysql, sizeof(mysql)); /* dummy mysql for set_mysql_extended_error */
@@ -269,23 +266,22 @@ int mysql_client_plugin_init()
load_env_plugins(&mysql);
- return 0;
+ DBUG_RETURN(0);
}
-
/**
Deinitializes the client plugin layer.
Unloades all client plugins and frees any associated resources.
*/
-
void mysql_client_plugin_deinit()
{
int i;
struct st_client_plugin_int *p;
+ DBUG_ENTER("mysql_client_plugin_deinit");
if (!initialized)
- return;
+ DBUG_VOID_RETURN;
for (i=0; i < MYSQL_CLIENT_MAX_PLUGINS; i++)
for (p= plugin_list[i]; p; p= p->next)
@@ -300,6 +296,7 @@ void mysql_client_plugin_deinit()
initialized= 0;
free_root(&mem_root, MYF(0));
pthread_mutex_destroy(&LOCK_load_client_plugin);
+ DBUG_VOID_RETURN;
}
/************* public facing functions, for client consumption *********/
@@ -310,10 +307,11 @@ mysql_client_register_plugin(MYSQL *mysql,
struct st_mysql_client_plugin *plugin)
{
va_list unused;
+ DBUG_ENTER("mysql_client_register_plugin");
LINT_INIT_STRUCT(unused);
if (is_not_initialized(mysql, plugin->name))
- return NULL;
+ DBUG_RETURN(NULL);
pthread_mutex_lock(&LOCK_load_client_plugin);
@@ -329,10 +327,9 @@ mysql_client_register_plugin(MYSQL *mysql,
plugin= add_plugin(mysql, plugin, 0, 0, unused);
pthread_mutex_unlock(&LOCK_load_client_plugin);
- return plugin;
+ DBUG_RETURN(plugin);
}
-
/* see <mysql/client_plugin.h> for a full description */
struct st_mysql_client_plugin *
mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
@@ -342,9 +339,14 @@ mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
char dlpath[FN_REFLEN+1];
void *sym, *dlhandle;
struct st_mysql_client_plugin *plugin;
+ DBUG_ENTER("mysql_load_plugin_v");
+ DBUG_PRINT ("entry", ("name=%s type=%d int argc=%d", name, type, argc));
if (is_not_initialized(mysql, name))
- return NULL;
+ {
+ DBUG_PRINT ("leave", ("mysql not initialized"));
+ DBUG_RETURN (NULL);
+ }
pthread_mutex_lock(&LOCK_load_client_plugin);
@@ -361,9 +363,11 @@ mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
mysql->options.extension->plugin_dir : PLUGINDIR, "/",
name, SO_EXT, NullS);
+ DBUG_PRINT ("info", ("dlopeninig %s", dlpath));
/* Open new dll handle */
if (!(dlhandle= dlopen(dlpath, RTLD_NOW)))
{
+ DBUG_PRINT ("info", ("failed to dlopen"));
errmsg= dlerror();
goto err;
}
@@ -399,37 +403,41 @@ mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
pthread_mutex_unlock(&LOCK_load_client_plugin);
- return plugin;
+ DBUG_PRINT ("leave", ("plugin loaded ok"));
+ DBUG_RETURN (plugin);
err:
pthread_mutex_unlock(&LOCK_load_client_plugin);
+ DBUG_PRINT ("leave", ("plugin load error : %s", errmsg));
set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name, errmsg);
- return NULL;
+ DBUG_RETURN (NULL);
}
-
/* see <mysql/client_plugin.h> for a full description */
struct st_mysql_client_plugin *
mysql_load_plugin(MYSQL *mysql, const char *name, int type, int argc, ...)
{
struct st_mysql_client_plugin *p;
va_list args;
+ DBUG_ENTER("mysql_load_plugin");
+
va_start(args, argc);
p= mysql_load_plugin_v(mysql, name, type, argc, args);
va_end(args);
- return p;
+ DBUG_RETURN(p);
}
-
/* see <mysql/client_plugin.h> for a full description */
struct st_mysql_client_plugin *
mysql_client_find_plugin(MYSQL *mysql, const char *name, int type)
{
struct st_mysql_client_plugin *p;
+ DBUG_ENTER("mysql_client_find_plugin");
+ DBUG_PRINT ("entry", ("name=%s, type=%d", name, type));
if (is_not_initialized(mysql, name))
- return NULL;
+ DBUG_RETURN (NULL);
if (type < 0 || type >= MYSQL_CLIENT_MAX_PLUGINS)
{
@@ -439,9 +447,26 @@ mysql_client_find_plugin(MYSQL *mysql, const char *name, int type)
}
if ((p= find_plugin(name, type)))
- return p;
+ {
+ DBUG_PRINT ("leave", ("found %p", p));
+ DBUG_RETURN (p);
+ }
/* not found, load it */
- return mysql_load_plugin(mysql, name, type, 0);
+ p= mysql_load_plugin(mysql, name, type, 0);
+ DBUG_PRINT ("leave", ("loaded %p", p));
+ DBUG_RETURN (p);
}
+
+/* see <mysql/client_plugin.h> for a full description */
+int mysql_plugin_options(struct st_mysql_client_plugin *plugin,
+ const char *option,
+ const void *value)
+{
+ DBUG_ENTER("mysql_plugin_options");
+ /* does the plugin support options call? */
+ if (!plugin || !plugin->options)
+ DBUG_RETURN(1);
+ DBUG_RETURN(plugin->options(option, value));
+}
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index d2f7a8641ba..83271aa91a0 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004-2006 MySQL AB
+/* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include <my_time.h>
#include <m_string.h>
@@ -77,7 +77,7 @@ uint calc_days_in_year(uint year)
*/
my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
- ulong flags, int *was_cut)
+ ulonglong flags, int *was_cut)
{
if (not_zero_date)
{
@@ -159,9 +159,9 @@ my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
enum enum_mysql_timestamp_type
str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
- ulong flags, int *was_cut)
+ ulonglong flags, int *was_cut)
{
- uint field_length, UNINIT_VAR(year_length), digits, i, number_of_fields;
+ uint UNINIT_VAR(field_length), UNINIT_VAR(year_length), digits, i, number_of_fields;
uint date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
uint add_hours= 0, start_loop;
ulong not_zero_date, allow_space;
@@ -174,8 +174,6 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
DBUG_ENTER("str_to_datetime");
DBUG_PRINT("enter",("str: %.*s",length,str));
- LINT_INIT(field_length);
-
if (flags & TIME_TIME_ONLY)
{
enum enum_mysql_timestamp_type ret;
@@ -491,7 +489,7 @@ err:
enum enum_mysql_timestamp_type
str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
- ulong fuzzydate, int *warning)
+ ulonglong fuzzydate, int *warning)
{
ulong date[5];
ulonglong value;
@@ -1071,10 +1069,10 @@ int my_time_to_str(const MYSQL_TIME *l_time, char *to, uint digits)
int my_date_to_str(const MYSQL_TIME *l_time, char *to)
{
- return my_sprintf(to, (to, "%04u-%02u-%02u",
- l_time->year,
- l_time->month,
- l_time->day));
+ return sprintf(to, "%04u-%02u-%02u",
+ l_time->year,
+ l_time->month,
+ l_time->day);
}
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint digits)
@@ -1154,7 +1152,7 @@ int my_TIME_to_str(const MYSQL_TIME *l_time, char *to, uint digits)
*/
longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res,
- uint flags, int *was_cut)
+ ulonglong flags, int *was_cut)
{
long part1,part2;
@@ -1180,7 +1178,12 @@ longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res,
nr= (nr+19000000L)*1000000L; /* YYMMDD, year: 1970-1999 */
goto ok;
}
- if (nr < 10000101L)
+ /*
+ Though officially we support DATE values from 1000-01-01 only, one can
+ easily insert a value like 1-1-1. So, for consistency reasons such dates
+ are allowed when TIME_FUZZY_DATE is set.
+ */
+ if (nr < 10000101L && !(flags & TIME_FUZZY_DATE))
goto err;
if (nr <= 99991231L)
{
diff --git a/sql-common/my_user.c b/sql-common/my_user.c
index 0b72e002977..8d717ea7131 100644
--- a/sql-common/my_user.c
+++ b/sql-common/my_user.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2005 MySQL AB
+/* Copyright (c) 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include <my_user.h>
#include <m_string.h>