diff options
Diffstat (limited to 'libmysql')
-rw-r--r-- | libmysql/Makefile.am | 29 | ||||
-rw-r--r-- | libmysql/Makefile.shared | 25 | ||||
-rw-r--r-- | libmysql/conf_to_src.c | 29 | ||||
-rw-r--r-- | libmysql/dll.c | 31 | ||||
-rw-r--r-- | libmysql/errmsg.c | 62 | ||||
-rw-r--r-- | libmysql/get_password.c | 31 | ||||
-rw-r--r-- | libmysql/libmysql.c | 972 | ||||
-rw-r--r-- | libmysql/libmysql.def | 124 | ||||
-rw-r--r-- | libmysql/manager.c | 264 | ||||
-rw-r--r-- | libmysql/net.c | 685 | ||||
-rw-r--r-- | libmysql/password.c | 31 | ||||
-rw-r--r-- | libmysql/violite.c | 443 |
12 files changed, 1281 insertions, 1445 deletions
diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index 85bca62d19c..fac544ba44d 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -17,11 +17,11 @@ # This file is public domain and comes with NO WARRANTY of any kind -target = libmysqlclient.la -target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ -LIBS = @CLIENT_LIBS@ +target = libmysqlclient.la +target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ -DMYSQL_CLIENT +LIBS = @CLIENT_LIBS@ INCLUDES = -I$(srcdir)/../include -I../include \ - -I$(srcdir)/.. -I$(top_srcdir) -I.. + -I$(srcdir)/.. -I$(top_srcdir) -I.. $(openssl_includes) include $(srcdir)/Makefile.shared @@ -36,10 +36,15 @@ link_sources: ss=`echo $(mystringsobjects) | sed "s;\.lo;.c;g"`; \ ds=`echo $(dbugobjects) | sed "s;\.lo;.c;g"`; \ ms=`echo $(mysysobjects) | sed "s;\.lo;.c;g"`; \ + vs=`echo $(vio_objects) | sed "s;\.lo;.c;g"`; \ for f in $$ss; do \ rm -f $(srcdir)/$$f; \ @LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \ done; \ + for f in $$vs; do \ + rm -f $(srcdir)/$$f; \ + @LN_CP_F@ $(srcdir)/../vio/$$f $(srcdir)/$$f; \ + done; \ for f in $(mystringsextra); do \ rm -f $(srcdir)/$$f; \ @LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \ @@ -48,6 +53,10 @@ link_sources: rm -f $(srcdir)/$$f; \ @LN_CP_F@ ../strings/$$f $(srcdir)/$$f; \ done; \ + for f in $$qs; do \ + rm -f $(srcdir)/$$f; \ + @LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \ + done; \ for f in $$ds; do \ rm -f $(srcdir)/$$f; \ @LN_CP_F@ $(srcdir)/../dbug/$$f $(srcdir)/$$f; \ @@ -55,7 +64,9 @@ link_sources: for f in $$ms $(mysysheaders); do \ rm -f $(srcdir)/$$f; \ @LN_CP_F@ $(srcdir)/../mysys/$$f $(srcdir)/$$f; \ - done; + done; \ + rm -f $(srcdir)/net.c; \ + @LN_CP_F@ $(srcdir)/../sql/net_serv.cc $(srcdir)/net.c # This part requires GNUmake # @@ -66,13 +77,13 @@ link_sources: # keep only the stubs for safemalloc.c and debug.c # # A list of needed headers collected from the deps information 000213 -nh = global.h config-win32.h dbug.h errmsg.h global.h \ +nh = my_global.h config-win32.h dbug.h errmsg.h \ m_ctype.h m_string.h \ my_alarm.h my_config.h my_dir.h my_list.h my_net.h my_sys.h \ - mysql.h mysql_com.h mysql_version.h mysqld_error.h mysys_err.h \ - my_pthread.h thr_alarm.h violite.h hash.h + mysql.h mysql_com.h mysql_version.h mysqld_error.h \ + mysys_err.h my_pthread.h thr_alarm.h violite.h hash.h # Get a list of the needed objects -lobjs = $(mysysobjects1) $(dbugobjects) $(mystringsobjects) +lobjs = $(mysysobjects1) $(dbugobjects) $(mystringsobjects) $(sqlobjects) do-lib-dist: dir=libmysql-$(MYSQL_NO_DASH_VERSION); \ diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index b1c7438543f..2bcf95f467d 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -31,13 +31,14 @@ noinst_PROGRAMS = conf_to_src CHARSET_OBJS=@CHARSET_OBJS@ LTCHARSET_OBJS= ${CHARSET_OBJS:.o=.lo} -target_sources = libmysql.c net.c violite.c password.c \ - get_password.c errmsg.c +target_sources = libmysql.c password.c manager.c \ + get_password.c errmsg.c -mystringsobjects = strmov.lo strxmov.lo strnmov.lo strmake.lo strend.lo \ +mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \ + strmake.lo strend.lo \ strnlen.lo strfill.lo is_prefix.lo \ int2str.lo str2int.lo strinstr.lo strcont.lo \ - strcend.lo \ + strcend.lo bcmp.lo \ bchange.lo bmove.lo bmove_upp.lo longlong2str.lo \ strtoull.lo strtoll.lo llstr.lo \ ctype.lo $(LTCHARSET_OBJS) @@ -56,13 +57,19 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \ mf_loadpath.lo my_pthread.lo my_thr_init.lo \ thr_mutex.lo mulalloc.lo string.lo default.lo \ my_compress.lo array.lo my_once.lo list.lo my_net.lo \ - charset.lo hash.lo mf_iocache.lo my_seek.lo \ - my_pread.lo mf_cache.lo my_gethostbyname.lo my_port.lo + charset.lo hash.lo mf_iocache.lo \ + mf_iocache2.lo my_seek.lo \ + my_pread.lo mf_cache.lo my_vsnprintf.lo md5.lo \ + my_getopt.lo my_gethostbyname.lo my_port.lo +sqlobjects = net.lo + # Not needed in the minimum library -mysysobjects2 = getopt.lo getopt1.lo getvar.lo my_lib.lo +mysysobjects2 = my_lib.lo mysysobjects = $(mysysobjects1) $(mysysobjects2) -target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) +target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \ + $(vio_objects) $(sqlobjects) target_ldflags = -version-info @SHARED_LIB_VERSION@ +vio_objects= vio.lo viosocket.lo viossl.lo viosslfactories.lo CLEANFILES = $(target_libadd) $(SHLIBOBJS) \ $(target) DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \ @@ -80,7 +87,7 @@ clean-local: `echo $(vio_objects) | sed "s;\.lo;.c;g"` \ $(CHARSET_SRCS) $(CHARSET_OBJS) \ $(mystringsextra) $(mystringsgen) $(mysysheaders) \ - ctype_extra_sources.c ../linked_client_sources + ctype_extra_sources.c net.c ../linked_client_sources ctype_extra_sources.c: conf_to_src ./conf_to_src $(top_srcdir) @CHARSETS_NEED_SOURCE@ > \ diff --git a/libmysql/conf_to_src.c b/libmysql/conf_to_src.c index 76316638153..95ffcf1cb2b 100644 --- a/libmysql/conf_to_src.c +++ b/libmysql/conf_to_src.c @@ -1,19 +1,18 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, +/* Copyright (C) 2000 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; either version 2 of the License, or + (at your option) any later version. + + 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ + 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 */ /* can't use -lmysys because this prog is used to create -lstrings */ diff --git a/libmysql/dll.c b/libmysql/dll.c index d1a23794025..f0a67d8f091 100644 --- a/libmysql/dll.c +++ b/libmysql/dll.c @@ -1,25 +1,24 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, +/* Copyright (C) 2000 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; either version 2 of the License, or + (at your option) any later version. + + 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ + 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 */ /* ** Handling initialization of the dll library */ -#include <global.h> +#include <my_global.h> #include <my_sys.h> #include <my_pthread.h> diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index 67cfe874f77..375ca7329c0 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -1,24 +1,23 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, +/* Copyright (C) 2000 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; either version 2 of the License, or + (at your option) any later version. + + 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ + 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 */ /* Error messages for MySQL clients */ -/* error messages for the demon is in share/language/errmsg.sys */ +/* error messages for the daemon is in share/language/errmsg.sys */ -#include <global.h> +#include <my_global.h> #include <my_sys.h> #include "errmsg.h" @@ -45,7 +44,14 @@ const char *client_errors[]= "Kann Named Pipe nicht oeffnen. Host: %-.64s pipe: %-.32s (%lu)", "Kann den Status der Named Pipe nicht setzen. Host: %-.64s pipe: %-.32s (%lu)", "Can't initialize character set %-.64s (path: %-.64s)", - "Got packet bigger than 'max_allowed_packet'" + "Got packet bigger than 'max_allowed_packet'", + "Embedded server", + "Error on SHOW SLAVE STATUS:", + "Error on SHOW SLAVE HOSTS:", + "Error connecting to slave:", + "Error connecting to master:", + "SSL connection error", + "Malformed packet" }; /* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */ @@ -58,7 +64,7 @@ const char *client_errors[]= "Não pode se conectar ao servidor MySQL local através do 'socket' '%-.64s' (%d)", "Não pode se conectar ao servidor MySQL em '%-.64s' (%d)", "Não pode criar 'socket TCP/IP' (%d)", - "'Host' servidor MySQL '%-.64s' (%d) desconhecido", + "'Host' servidor MySQL '%-.64s' (%d) desconhecido", "Servidor MySQL desapareceu", "Incompatibilidade de protocolos. Versão do Servidor: %d - Versão do Cliente: %d", "Cliente do MySQL com falta de memória", @@ -73,7 +79,14 @@ const char *client_errors[]= "Não pode abrir 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", "Não pode estabelecer o estado do 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", "Não pode inicializar conjunto de caracteres %-.64s (caminho %-.64s)", - "Obteve pacote maior do que 'max_allowed_packet'" + "Obteve pacote maior do que 'max_allowed_packet'", + "Embedded server" + "Error on SHOW SLAVE STATUS:", + "Error on SHOW SLAVE HOSTS:", + "Error connecting to slave:", + "Error connecting to master:", + "SSL connection error", + "Malformed packet" }; #else /* ENGLISH */ @@ -99,7 +112,14 @@ const char *client_errors[]= "Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)", "Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)", "Can't initialize character set %-.64s (path: %-.64s)", - "Got packet bigger than 'max_allowed_packet'" + "Got packet bigger than 'max_allowed_packet'", + "Embedded server", + "Error on SHOW SLAVE STATUS:", + "Error on SHOW SLAVE HOSTS:", + "Error connecting to slave:", + "Error connecting to master:", + "SSL connection error", + "Malformed packet" }; #endif diff --git a/libmysql/get_password.c b/libmysql/get_password.c index 989de9dd11a..124c315a821 100644 --- a/libmysql/get_password.c +++ b/libmysql/get_password.c @@ -1,25 +1,24 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, +/* Copyright (C) 2000 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; either version 2 of the License, or + (at your option) any later version. + + 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ + 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 */ /* ** Ask for a password from tty ** This is an own file to avoid conflicts with curses */ -#include <global.h> +#include <my_global.h> #include <my_sys.h> #include "mysql.h" #include <m_string.h> diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 755d85dd04a..152177c0fbe 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1,21 +1,20 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, +/* Copyright (C) 2000 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; either version 2 of the License, or + (at your option) any later version. + + 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -#include <global.h> + 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 */ + +#include <my_global.h> #if defined(__WIN__) || defined(_WIN32) || defined(_WIN64) #include <winsock.h> #include <odbcinst.h> @@ -60,6 +59,10 @@ static my_bool mysql_client_init=0; uint mysql_port=0; my_string mysql_unix_port=0; +ulong net_buffer_length=8192; +ulong max_allowed_packet= 1024L*1024L*1024L; +ulong net_read_timeout= NET_READ_TIMEOUT; +ulong net_write_timeout= NET_WRITE_TIMEOUT; #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS) @@ -70,7 +73,7 @@ my_string mysql_unix_port=0; #endif #if defined(MSDOS) || defined(__WIN__) -// socket_errno is defined in global.h for all platforms +// socket_errno is defined in my_global.h for all platforms #define perror(A) #else #include <errno.h> @@ -91,6 +94,38 @@ static sig_handler pipe_sig_handler(int sig); static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, const char *from, ulong length); +static my_bool org_my_init_done=0; + +int STDCALL mysql_server_init(int argc __attribute__((unused)), + char **argv __attribute__((unused)), + char **groups __attribute__((unused))) +{ + return 0; +} + +void STDCALL mysql_server_end() +{ + /* If library called my_init(), free memory allocated by it */ + if (!org_my_init_done) + my_end(0); +} + +my_bool STDCALL mysql_thread_init() +{ +#ifdef THREAD + return my_thread_init(); +#else + return 0; +#endif +} + +void STDCALL mysql_thread_end() +{ +#ifdef THREAD + my_thread_end(); +#endif +} + /* Let the user specify that we don't want SIGPIPE; This doesn't however work with threaded applications as we can have multiple read in progress. @@ -106,17 +141,23 @@ static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, #define reset_sigpipe(mysql) #endif +static MYSQL* spawn_init(MYSQL* parent, const char* host, + unsigned int port, + const char* user, + const char* passwd); + + /**************************************************************************** -* A modified version of connect(). connect2() allows you to specify -* a timeout value, in seconds, that we should wait until we -* derermine we can't connect to a particular host. If timeout is 0, -* connect2() will behave exactly like connect(). -* -* Base version coded by Steve Bernacki, Jr. <steve@navinet.net> + A modified version of connect(). connect2() allows you to specify + a timeout value, in seconds, that we should wait until we + derermine we can't connect to a particular host. If timeout is 0, + my_connect() will behave exactly like connect(). + + Base version coded by Steve Bernacki, Jr. <steve@navinet.net> *****************************************************************************/ -static int connect2(my_socket s, const struct sockaddr *name, uint namelen, - uint timeout) +int my_connect(my_socket s, const struct sockaddr *name, uint namelen, + uint timeout) { #if defined(__WIN__) || defined(OS2) return connect(s, (struct sockaddr*) name, namelen); @@ -180,7 +221,7 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen, { tv.tv_sec = (long) timeout; tv.tv_usec = 0; -#if defined(HPUX) && defined(THREAD) +#if defined(HPUX10) && defined(THREAD) if ((res = select(s+1, NULL, (int*) &sfds, NULL, &tv)) >= 0) break; #else @@ -212,7 +253,7 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen, } /* -** Create a named pipe connection + Create a named pipe connection */ #ifdef __WIN__ @@ -285,15 +326,15 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, /***************************************************************************** -** read a packet from server. Give error message if socket was down -** or packet is an error message + read a packet from server. Give error message if socket was down + or packet is an error message *****************************************************************************/ -uint +ulong net_safe_read(MYSQL *mysql) { NET *net= &mysql->net; - uint len=0; + ulong len=0; init_sigpipe_variables /* Don't give sigpipe errors if the client doesn't want them */ @@ -311,26 +352,18 @@ net_safe_read(MYSQL *mysql) CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST); strmov(net->last_error,ER(net->last_errno)); - return(packet_error); + return (packet_error); } if (net->read_pos[0] == 255) { if (len > 3) { char *pos=(char*) net->read_pos+1; - if (mysql->protocol_version > 9) - { /* New client protocol */ - net->last_errno=uint2korr(pos); - pos+=2; - len-=2; - } - else - { - net->last_errno=CR_UNKNOWN_ERROR; - len--; - } + net->last_errno=uint2korr(pos); + pos+=2; + len-=2; (void) strmake(net->last_error,(char*) pos, - min(len,sizeof(net->last_error)-1)); + min((uint) len,(uint) sizeof(net->last_error)-1)); } else { @@ -421,7 +454,7 @@ static void free_rows(MYSQL_DATA *cur) int simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, - uint length, my_bool skipp_check) + ulong length, my_bool skipp_check) { NET *net= &mysql->net; int result= -1; @@ -432,11 +465,7 @@ simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, if (mysql->net.vio == 0) { /* Do reconnect if possible */ if (mysql_reconnect(mysql)) - { - net->last_errno=CR_SERVER_GONE_ERROR; - strmov(net->last_error,ER(net->last_errno)); goto end; - } } if (mysql->status != MYSQL_STATUS_READY) { @@ -457,8 +486,9 @@ simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, { DBUG_PRINT("error",("Can't send command to server. Error: %d",socket_errno)); end_server(mysql); - if (mysql_reconnect(mysql) || - net_write_command(net,(uchar) command,arg, + if (mysql_reconnect(mysql)) + goto end; + if (net_write_command(net,(uchar) command,arg, length ? length : (ulong) strlen(arg))) { net->last_errno=CR_SERVER_GONE_ERROR; @@ -540,7 +570,7 @@ static my_bool is_NT(void) #endif /* -** Expand wildcard to a sql string + Expand wildcard to a sql string */ static void @@ -566,7 +596,7 @@ append_wild(char *to, char *end, const char *wild) /************************************************************************** -** Init debugging if MYSQL_DEBUG environment variable is found + Init debugging if MYSQL_DEBUG environment variable is found **************************************************************************/ void STDCALL @@ -603,7 +633,7 @@ mysql_debug(const char *debug __attribute__((unused))) /************************************************************************** -** Close the server connection if we get a SIGPIPE + Close the server connection if we get a SIGPIPE ARGSUSED **************************************************************************/ @@ -618,7 +648,7 @@ pipe_sig_handler(int sig __attribute__((unused))) /************************************************************************** -** Shut down connection + Shut down connection **************************************************************************/ static void @@ -652,8 +682,8 @@ mysql_free_result(MYSQL_RES *result) DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows")); for (;;) { - uint pkt_len; - if ((pkt_len=(uint) net_safe_read(result->handle)) == packet_error) + ulong pkt_len; + if ((pkt_len=net_safe_read(result->handle)) == packet_error) break; if (pkt_len == 1 && result->handle->net.read_pos[0] == 254) break; /* End of data */ @@ -672,7 +702,7 @@ mysql_free_result(MYSQL_RES *result) /**************************************************************************** -** Get options from my.cnf + Get options from my.cnf ****************************************************************************/ static const char *default_options[]= @@ -682,7 +712,9 @@ 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", - NullS + "replication-probe", "enable-reads-from-master", "repl-parse-query", + "ssl-cipher", "max-allowed-packet", + NullS }; static TYPELIB option_types={array_elements(default_options)-1, @@ -826,6 +858,18 @@ static void mysql_read_default_options(struct st_mysql_options *options, break; case 22: options->client_flag&= CLIENT_LOCAL_FILES; + break; + case 23: /* replication probe */ + options->rpl_probe= 1; + break; + case 24: /* enable-reads-from-master */ + options->no_master_reads= 0; + break; + case 25: /* repl-parse-query */ + options->rpl_parse= 1; + break; + case 27: + options->max_allowed_packet= atoi(opt_arg); break; default: DBUG_PRINT("warning",("unknown option: %s",option[0])); @@ -839,7 +883,7 @@ static void mysql_read_default_options(struct st_mysql_options *options, /*************************************************************************** -** Change field rows to field structs + Change field rows to field structs ***************************************************************************/ static MYSQL_FIELD * @@ -850,13 +894,14 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, MYSQL_FIELD *field,*result; DBUG_ENTER("unpack_fields"); - field=result=(MYSQL_FIELD*) alloc_root(alloc,sizeof(MYSQL_FIELD)*fields); + field=result=(MYSQL_FIELD*) alloc_root(alloc, + (uint) sizeof(MYSQL_FIELD)*fields); if (!result) DBUG_RETURN(0); for (row=data->data; row ; row = row->next,field++) { - field->table= strdup_root(alloc,(char*) row->data[0]); + field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]); field->name= strdup_root(alloc,(char*) row->data[1]); field->length= (uint) uint3korr(row->data[2]); field->type= (enum enum_field_types) (uchar) row->data[3][0]; @@ -888,7 +933,8 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, uint fields) { - uint field,pkt_len; + uint field; + ulong pkt_len; ulong len; uchar *cp; char *to, *end_to; @@ -897,7 +943,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, NET *net = &mysql->net; DBUG_ENTER("read_rows"); - if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error) + if ((pkt_len= net_safe_read(mysql)) == packet_error) DBUG_RETURN(0); if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), MYF(MY_WME | MY_ZEROFILL)))) @@ -942,7 +988,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, if (len > (ulong) (end_to - to)) { free_rows(result); - net->last_errno=CR_UNKNOWN_ERROR; + net->last_errno=CR_MALFORMED_PACKET; strmov(net->last_error,ER(net->last_errno)); DBUG_RETURN(0); } @@ -970,8 +1016,8 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, /* -** Read one row. Uses packet buffer as storage for fields. -** When next packet is read, the previous field values are destroyed + Read one row. Uses packet buffer as storage for fields. + When next packet is read, the previous field values are destroyed */ @@ -982,7 +1028,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) ulong pkt_len,len; uchar *pos,*prev_pos, *end_pos; - if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error) + if ((pkt_len=net_safe_read(mysql)) == packet_error) return -1; if (pkt_len == 1 && mysql->net.read_pos[0] == 254) return 1; /* End of data */ @@ -1017,8 +1063,301 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) return 0; } +/* perform query on master */ +int STDCALL mysql_master_query(MYSQL *mysql, const char *q, + unsigned long length) +{ + DBUG_ENTER("mysql_master_query"); + if (mysql_master_send_query(mysql, q, length)) + DBUG_RETURN(1); + DBUG_RETURN(mysql_read_query_result(mysql)); +} + +int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q, + unsigned long length) +{ + MYSQL *master = mysql->master; + DBUG_ENTER("mysql_master_send_query"); + if (!master->net.vio && !mysql_real_connect(master,0,0,0,0,0,0,0)) + DBUG_RETURN(1); + mysql->last_used_con = master; + DBUG_RETURN(simple_command(master, COM_QUERY, q, length, 1)); +} + + +/* perform query on slave */ +int STDCALL mysql_slave_query(MYSQL *mysql, const char *q, + unsigned long length) +{ + DBUG_ENTER("mysql_slave_query"); + if (mysql_slave_send_query(mysql, q, length)) + DBUG_RETURN(1); + DBUG_RETURN(mysql_read_query_result(mysql)); +} + +int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q, + unsigned long length) +{ + MYSQL* last_used_slave, *slave_to_use = 0; + DBUG_ENTER("mysql_slave_send_query"); + + if ((last_used_slave = mysql->last_used_slave)) + slave_to_use = last_used_slave->next_slave; + else + slave_to_use = mysql->next_slave; + /* + Next_slave is always safe to use - we have a circular list of slaves + if there are no slaves, mysql->next_slave == mysql + */ + mysql->last_used_con = mysql->last_used_slave = slave_to_use; + if (!slave_to_use->net.vio && !mysql_real_connect(slave_to_use, 0,0,0, + 0,0,0,0)) + DBUG_RETURN(1); + DBUG_RETURN(simple_command(slave_to_use, COM_QUERY, q, length, 1)); +} + + +/* enable/disable parsing of all queries to decide + if they go on master or slave */ +void STDCALL mysql_enable_rpl_parse(MYSQL* mysql) +{ + mysql->options.rpl_parse = 1; +} + +void STDCALL mysql_disable_rpl_parse(MYSQL* mysql) +{ + mysql->options.rpl_parse = 0; +} + +/* get the value of the parse flag */ +int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql) +{ + return mysql->options.rpl_parse; +} + +/* enable/disable reads from master */ +void STDCALL mysql_enable_reads_from_master(MYSQL* mysql) +{ + mysql->options.no_master_reads = 0; +} + +void STDCALL mysql_disable_reads_from_master(MYSQL* mysql) +{ + mysql->options.no_master_reads = 1; +} + +/* get the value of the master read flag */ +int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql) +{ + return !(mysql->options.no_master_reads); +} + + +/* + We may get an error while doing replication internals. + In this case, we add a special explanation to the original + error +*/ + +static void expand_error(MYSQL* mysql, int error) +{ + char tmp[MYSQL_ERRMSG_SIZE]; + char *p; + uint err_length; + strmake(tmp, mysql->net.last_error, MYSQL_ERRMSG_SIZE-1); + p = strmake(mysql->net.last_error, ER(error), MYSQL_ERRMSG_SIZE-1); + err_length= (uint) (p - mysql->net.last_error); + strmake(p, tmp, MYSQL_ERRMSG_SIZE-1 - err_length); + mysql->net.last_errno = error; +} + +/* + This function assumes we have just called SHOW SLAVE STATUS and have + read the given result and row +*/ + +static int get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row) +{ + MYSQL* master; + DBUG_ENTER("get_master"); + if (mysql_num_fields(res) < 3) + DBUG_RETURN(1); /* safety */ + + /* use the same username and password as the original connection */ + if (!(master = spawn_init(mysql, row[0], atoi(row[2]), 0, 0))) + DBUG_RETURN(1); + mysql->master = master; + DBUG_RETURN(0); +} + + +/* + Assuming we already know that mysql points to a master connection, + retrieve all the slaves +*/ + +static int get_slaves_from_master(MYSQL* mysql) +{ + MYSQL_RES* res = 0; + MYSQL_ROW row; + int error = 1; + int has_auth_info; + int port_ind; + DBUG_ENTER("get_slaves_from_master"); + + if (!mysql->net.vio && !mysql_real_connect(mysql,0,0,0,0,0,0,0)) + { + expand_error(mysql, CR_PROBE_MASTER_CONNECT); + DBUG_RETURN(1); + } + + if (mysql_query(mysql, "SHOW SLAVE HOSTS") || + !(res = mysql_store_result(mysql))) + { + expand_error(mysql, CR_PROBE_SLAVE_HOSTS); + DBUG_RETURN(1); + } + + switch (mysql_num_fields(res)) { + case 5: + has_auth_info = 0; + port_ind=2; + break; + case 7: + has_auth_info = 1; + port_ind=4; + break; + default: + goto err; + } + + while ((row = mysql_fetch_row(res))) + { + MYSQL* slave; + const char* tmp_user, *tmp_pass; + + if (has_auth_info) + { + tmp_user = row[2]; + tmp_pass = row[3]; + } + else + { + tmp_user = mysql->user; + tmp_pass = mysql->passwd; + } + + if (!(slave = spawn_init(mysql, row[1], atoi(row[port_ind]), + tmp_user, tmp_pass))) + goto err; + + /* Now add slave into the circular linked list */ + slave->next_slave = mysql->next_slave; + mysql->next_slave = slave; + } + error = 0; +err: + if (res) + mysql_free_result(res); + DBUG_RETURN(error); +} + + +int STDCALL mysql_rpl_probe(MYSQL* mysql) +{ + MYSQL_RES *res= 0; + MYSQL_ROW row; + int error = 1; + DBUG_ENTER("mysql_rpl_probe"); + + /* + First determine the replication role of the server we connected to + the most reliable way to do this is to run SHOW SLAVE STATUS and see + if we have a non-empty master host. This is still not fool-proof - + it is not a sin to have a master that has a dormant slave thread with + a non-empty master host. However, it is more reliable to check + for empty master than whether the slave thread is actually running + */ + if (mysql_query(mysql, "SHOW SLAVE STATUS") || + !(res = mysql_store_result(mysql))) + { + expand_error(mysql, CR_PROBE_SLAVE_STATUS); + DBUG_RETURN(1); + } + + row= mysql_fetch_row(res); + /* + Check master host for emptiness/NULL + For MySQL 4.0 it's enough to check for row[0] + */ + if (row && row[0] && *(row[0])) + { + /* this is a slave, ask it for the master */ + if (get_master(mysql, res, row) || get_slaves_from_master(mysql)) + goto err; + } + else + { + mysql->master = mysql; + if (get_slaves_from_master(mysql)) + goto err; + } + + error = 0; +err: + if (res) + mysql_free_result(res); + DBUG_RETURN(error); +} + + +/* + Make a not so fool-proof decision on where the query should go, to + the master or the slave. Ideally the user should always make this + decision himself with mysql_master_query() or mysql_slave_query(). + However, to be able to more easily port the old code, we support the + option of an educated guess - this should work for most applications, + however, it may make the wrong decision in some particular cases. If + that happens, the user would have to change the code to call + mysql_master_query() or mysql_slave_query() explicitly in the place + where we have made the wrong decision +*/ + +enum mysql_rpl_type +STDCALL mysql_rpl_query_type(const char* q, int len) +{ + const char *q_end= q + len; + for (; q < q_end; ++q) + { + char c; + if (isalpha(c=*q)) + { + switch(tolower(c)) { + case 'i': /* insert */ + case 'u': /* update or unlock tables */ + case 'l': /* lock tables or load data infile */ + case 'd': /* drop or delete */ + case 'a': /* alter */ + return MYSQL_RPL_MASTER; + case 'c': /* create or check */ + return tolower(q[1]) == 'h' ? MYSQL_RPL_ADMIN : MYSQL_RPL_MASTER ; + case 's': /* select or show */ + return tolower(q[1]) == 'h' ? MYSQL_RPL_ADMIN : MYSQL_RPL_SLAVE; + case 'f': /* flush */ + case 'r': /* repair */ + case 'g': /* grant */ + return MYSQL_RPL_ADMIN; + default: + return MYSQL_RPL_SLAVE; + } + } + } + return MYSQL_RPL_MASTER; /* By default, send to master */ +} + + /**************************************************************************** -** Init MySQL structure or allocate one + Init MySQL structure or allocate one ****************************************************************************/ MYSQL * STDCALL @@ -1030,11 +1369,17 @@ mysql_init(MYSQL *mysql) if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL)))) return 0; mysql->free_me=1; - mysql->net.vio = 0; } else bzero((char*) (mysql),sizeof(*(mysql))); mysql->options.connect_timeout=CONNECT_TIMEOUT; + mysql->last_used_con = mysql->next_slave = mysql->master = mysql; + + /* + By default, we are a replication pivot. The caller must reset it + after we return if this is not the case. + */ + mysql->rpl_pivot = 1; #if defined(SIGPIPE) && defined(THREAD) && !defined(__WIN__) if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE)) (void) signal(SIGPIPE,pipe_sig_handler); @@ -1056,6 +1401,7 @@ static void mysql_once_init() if (!mysql_client_init) { mysql_client_init=1; + org_my_init_done=my_init_done; my_init(); /* Will init threads */ init_client_errs(); if (!mysql_port) @@ -1094,63 +1440,64 @@ static void mysql_once_init() #endif } -#ifdef HAVE_OPENSSL /************************************************************************** -** Fill in SSL part of MYSQL structure and set 'use_ssl' flag. -** NB! Errors are not reported until you do mysql_real_connect. + Fill in SSL part of MYSQL structure and set 'use_ssl' flag. + NB! Errors are not reported until you do mysql_real_connect. **************************************************************************/ -int STDCALL -mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert, - const char *ca, const char *capath) -{ - mysql->options.ssl_key = key==0 ? 0 : my_strdup(key,MYF(0)); - mysql->options.ssl_cert = cert==0 ? 0 : my_strdup(cert,MYF(0)); - mysql->options.ssl_ca = ca==0 ? 0 : my_strdup(ca,MYF(0)); - mysql->options.ssl_capath = capath==0 ? 0 : my_strdup(capath,MYF(0)); - mysql->options.use_ssl = true; - mysql->connector_fd = new_VioSSLConnectorFd(key, cert, ca, capath); - return 0; -} - -/************************************************************************** -**************************************************************************/ +#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME)) -char * STDCALL -mysql_ssl_cipher(MYSQL *mysql) +int STDCALL +mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , + const char *key __attribute__((unused)), + const char *cert __attribute__((unused)), + const char *ca __attribute__((unused)), + const char *capath __attribute__((unused)), + const char *cipher __attribute__((unused))) { - return (char *)mysql->net.vio->cipher_description(); +#ifdef HAVE_OPENSSL + 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 + return 0; } /************************************************************************** -** Free strings in the SSL structure and clear 'use_ssl' flag. -** NB! Errors are not reported until you do mysql_real_connect. + Free strings in the SSL structure and clear 'use_ssl' flag. + NB! Errors are not reported until you do mysql_real_connect. **************************************************************************/ -int STDCALL -mysql_ssl_clear(MYSQL *mysql) +static int +mysql_ssl_free(MYSQL *mysql __attribute__((unused))) { +#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->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); mysql->options.ssl_key = 0; mysql->options.ssl_cert = 0; mysql->options.ssl_ca = 0; mysql->options.ssl_capath = 0; - mysql->options.use_ssl = false; - mysql->connector_fd->delete(); + mysql->options.ssl_cipher= 0; + mysql->options.use_ssl = FALSE; mysql->connector_fd = 0; +#endif /* HAVE_OPENSSL */ return 0; } -#endif /* HAVE_OPENSSL */ /************************************************************************** -** Connect to sql server -** If host == 0 then use localhost + Connect to sql server + If host == 0 then use localhost **************************************************************************/ +#ifdef USE_OLD_FUNCTIONS MYSQL * STDCALL mysql_connect(MYSQL *mysql,const char *host, const char *user, const char *passwd) @@ -1167,11 +1514,12 @@ mysql_connect(MYSQL *mysql,const char *host, DBUG_RETURN(res); } } +#endif /* -** Note that the mysql argument must be initialized with mysql_init() -** before calling mysql_real_connect ! + Note that the mysql argument must be initialized with mysql_init() + before calling mysql_real_connect ! */ MYSQL * STDCALL @@ -1184,7 +1532,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, my_socket sock; uint32 ip_addr; struct sockaddr_in sock_addr; - uint pkt_length; + ulong pkt_length; NET *net= &mysql->net; #ifdef __WIN__ HANDLE hPipe=INVALID_HANDLE_VALUE; @@ -1194,6 +1542,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, #endif init_sigpipe_variables DBUG_ENTER("mysql_real_connect"); + LINT_INIT(host_info); DBUG_PRINT("enter",("host: %s db: %s user: %s", host ? host : "(Null)", @@ -1260,7 +1609,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); UNIXaddr.sun_family = AF_UNIX; strmov(UNIXaddr.sun_path, unix_socket); - if (connect2(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), + if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), mysql->options.connect_timeout) <0) { DBUG_PRINT("error",("Got error %d on connect to local server",socket_errno)); @@ -1291,7 +1640,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (mysql->options.named_pipe || (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE))) + { + net->last_errno= CR_SERVER_LOST; + strmov(net->last_error,ER(net->last_errno)); goto error; /* User only requested named pipes */ + } /* Try also with TCP/IP */ } else @@ -1340,16 +1693,16 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, &tmp_errno); if (!hp) { + my_gethostbyname_r_free(); net->last_errno=CR_UNKNOWN_HOST; sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno); - my_gethostbyname_r_free(); goto error; } memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length); my_gethostbyname_r_free(); } sock_addr.sin_port = (ushort) htons((ushort) port); - if (connect2(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), + if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), mysql->options.connect_timeout) <0) { DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,host)); @@ -1387,8 +1740,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_DUMP("packet",(char*) net->read_pos,10); DBUG_PRINT("info",("mysql protocol version %d, server=%d", PROTOCOL_VERSION, mysql->protocol_version)); - if (mysql->protocol_version != PROTOCOL_VERSION && - mysql->protocol_version != PROTOCOL_VERSION-1) + if (mysql->protocol_version != PROTOCOL_VERSION) { net->last_errno= CR_VERSION_ERROR; sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version, @@ -1424,7 +1776,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, charset_name=charset_name_buff; sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */ if (!(mysql->charset = - get_charset((uint8) mysql->server_language, MYF(MY_WME)))) + get_charset((uint8) mysql->server_language, MYF(0)))) mysql->charset = default_charset_info; /* shouldn't be fatal */ } @@ -1480,6 +1832,10 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, client_flag|=CLIENT_CAPABILITIES; #ifdef HAVE_OPENSSL + if (mysql->options.ssl_key || mysql->options.ssl_cert || + mysql->options.ssl_ca || mysql->options.ssl_capath || + mysql->options.ssl_cipher) + mysql->options.use_ssl= 1; if (mysql->options.use_ssl) client_flag|=CLIENT_SSL; #endif /* HAVE_OPENSSL */ @@ -1514,19 +1870,40 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, mysql->client_flag=client_flag; #ifdef HAVE_OPENSSL - /* Oops.. are we careful enough to not send ANY information */ - /* without encryption? */ + /* + Oops.. are we careful enough to not send ANY information without + encryption? + */ if (client_flag & CLIENT_SSL) { + struct st_mysql_options *options= &mysql->options; if (my_net_write(net,buff,(uint) (2)) || net_flush(net)) + { + net->last_errno= CR_SERVER_LOST; + strmov(net->last_error,ER(net->last_errno)); goto error; + } /* Do the SSL layering. */ + if (!(mysql->connector_fd= + (gptr) new_VioSSLConnectorFd(options->ssl_key, + options->ssl_cert, + options->ssl_ca, + options->ssl_capath, + options->ssl_cipher))) + { + net->last_errno= CR_SSL_CONNECTION_ERROR; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } DBUG_PRINT("info", ("IO layer change in progress...")); - VioSSLConnectorFd* connector_fd = (VioSSLConnectorFd*) - (mysql->connector_fd); - VioSocket* vio_socket = (VioSocket*)(mysql->net.vio); - VioSSL* vio_ssl = connector_fd->connect(vio_socket); - mysql->net.vio = (NetVio*)(vio_ssl); + if(sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd), + mysql->net.vio, (long) (mysql->options.connect_timeout))) + { + net->last_errno= CR_SSL_CONNECTION_ERROR; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } + DBUG_PRINT("info", ("IO layer change done!")); } #endif /* HAVE_OPENSSL */ @@ -1534,6 +1911,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, mysql->server_version,mysql->server_capabilities, mysql->server_status, client_flag)); + /* This needs to be changed as it's not useful with big packets */ int3store(buff+2,max_allowed_packet); if (user && user[0]) strmake(buff+5,user,32); /* Max user name */ @@ -1551,11 +1929,18 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, mysql->db=my_strdup(db,MYF(MY_WME)); db=0; } - if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net) || - net_safe_read(mysql) == packet_error) + if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) + { + net->last_errno= CR_SERVER_LOST; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } + if (net_safe_read(mysql) == packet_error) goto error; if (client_flag & CLIENT_COMPRESS) /* We will use compression */ net->compress=1; + if (mysql->options.max_allowed_packet) + net->max_packet_size= mysql->options.max_allowed_packet; if (db && mysql_select_db(mysql,db)) goto error; if (mysql->options.init_command) @@ -1568,6 +1953,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, mysql->reconnect=reconnect; } + if (mysql->options.rpl_probe && mysql_rpl_probe(mysql)) + goto error; + DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); reset_sigpipe(mysql); DBUG_RETURN(mysql); @@ -1587,6 +1975,26 @@ error: } +/* needed when we move MYSQL structure to a different address */ + +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; +} + + static my_bool mysql_reconnect(MYSQL *mysql) { MYSQL tmp_mysql; @@ -1595,21 +2003,29 @@ static my_bool mysql_reconnect(MYSQL *mysql) if (!mysql->reconnect || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) { - /* Allov reconnect next time */ + /* Allow reconnect next time */ mysql->server_status&= ~SERVER_STATUS_IN_TRANS; + mysql->net.last_errno=CR_SERVER_GONE_ERROR; + strmov(mysql->net.last_error,ER(mysql->net.last_errno)); DBUG_RETURN(1); } mysql_init(&tmp_mysql); tmp_mysql.options=mysql->options; bzero((char*) &mysql->options,sizeof(mysql->options)); + 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)) + { + mysql->net.last_errno= tmp_mysql.net.last_errno; + strmov(mysql->net.last_error, tmp_mysql.net.last_error); DBUG_RETURN(1); + } tmp_mysql.free_me=mysql->free_me; mysql->free_me=0; mysql_close(mysql); *mysql=tmp_mysql; + mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */ net_clear(&mysql->net); mysql->affected_rows= ~(my_ulonglong) 0; DBUG_RETURN(0); @@ -1617,7 +2033,7 @@ static my_bool mysql_reconnect(MYSQL *mysql) /************************************************************************** -** Change user and database + Change user and database **************************************************************************/ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, @@ -1635,7 +2051,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, pos=scramble(pos, mysql->scramble_buff, passwd, (my_bool) (mysql->protocol_version == 9)); pos=strmov(pos+1,db ? db : ""); - if (simple_command(mysql,COM_CHANGE_USER, buff,(uint) (pos-buff),0)) + if (simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (pos-buff),0)) DBUG_RETURN(1); my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); @@ -1650,7 +2066,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, /************************************************************************** -** Set current database + Set current database **************************************************************************/ int STDCALL @@ -1660,7 +2076,7 @@ mysql_select_db(MYSQL *mysql, const char *db) DBUG_ENTER("mysql_select_db"); DBUG_PRINT("enter",("db: '%s'",db)); - if ((error=simple_command(mysql,COM_INIT_DB,db,(uint) strlen(db),0))) + if ((error=simple_command(mysql,COM_INIT_DB,db,(ulong) strlen(db),0))) DBUG_RETURN(error); my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); mysql->db=my_strdup(db,MYF(MY_WME)); @@ -1669,8 +2085,8 @@ mysql_select_db(MYSQL *mysql, const char *db) /************************************************************************* -** Send a QUIT to the server and close the connection -** If handle is alloced by mysql connect free it. + Send a QUIT to the server and close the connection + If handle is alloced by mysql connect free it. *************************************************************************/ void STDCALL @@ -1685,7 +2101,7 @@ mysql_close(MYSQL *mysql) mysql->status=MYSQL_STATUS_READY; /* Force command */ mysql->reconnect=0; simple_command(mysql,COM_QUIT,NullS,0,1); - end_server(mysql); + end_server(mysql); /* Sets mysql->net.vio= 0 */ } my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); @@ -1701,14 +2117,28 @@ mysql_close(MYSQL *mysql) 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)); +#ifdef HAVE_OPENSSL + mysql_ssl_free(mysql); +#endif /* HAVE_OPENSSL */ /* Clear pointers for better safety */ mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; bzero((char*) &mysql->options,sizeof(mysql->options)); - mysql->net.vio = 0; -#ifdef HAVE_OPENSSL - ((VioConnectorFd*)(mysql->connector_fd))->delete(); - mysql->connector_fd = 0; -#endif /* HAVE_OPENSSL */ + + /* 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; + } + if (mysql != mysql->master) + mysql_close(mysql->master); if (mysql->free_me) my_free((gptr) mysql,MYF(0)); } @@ -1717,8 +2147,8 @@ mysql_close(MYSQL *mysql) /************************************************************************** -** Do a query. If query returned rows, free old rows. -** Read data by mysql_store_result or by repeat call of mysql_fetch_row + Do a query. If query returned rows, free old rows. + Read data by mysql_store_result or by repeat call of mysql_fetch_row **************************************************************************/ int STDCALL @@ -1727,6 +2157,68 @@ mysql_query(MYSQL *mysql, const char *query) return mysql_real_query(mysql,query, (uint) strlen(query)); } + +static MYSQL* spawn_init(MYSQL* parent, const char* host, + unsigned int port, const char* user, + const char* passwd) +{ + MYSQL* child; + if (!(child = mysql_init(0))) + return 0; + + child->options.user = my_strdup((user) ? user : + (parent->user ? parent->user : + parent->options.user), MYF(0)); + child->options.password = my_strdup((passwd) ? passwd : + (parent->passwd ? + parent->passwd : + parent->options.password), MYF(0)); + child->options.port = port; + child->options.host = my_strdup((host) ? host : + (parent->host ? + parent->host : + parent->options.host), MYF(0)); + if (parent->db) + child->options.db = my_strdup(parent->db, MYF(0)); + else if (parent->options.db) + child->options.db = my_strdup(parent->options.db, MYF(0)); + + child->options.rpl_parse = child->options.rpl_probe = child->rpl_pivot = 0; + + return child; +} + + +int +STDCALL mysql_set_master(MYSQL* mysql, const char* host, + unsigned int port, const char* user, + const char* passwd) +{ + if (mysql->master != mysql && !mysql->master->rpl_pivot) + mysql_close(mysql->master); + if (!(mysql->master = spawn_init(mysql, host, port, user, passwd))) + return 1; + mysql->master->rpl_pivot = 0; + mysql->master->options.rpl_parse = 0; + mysql->master->options.rpl_probe = 0; + return 0; +} + +int +STDCALL mysql_add_slave(MYSQL* mysql, const char* host, + unsigned int port, + const char* user, + const char* passwd) +{ + MYSQL* slave; + if (!(slave = spawn_init(mysql, host, port, user, passwd))) + return 1; + slave->next_slave = mysql->next_slave; + mysql->next_slave = slave; + return 0; +} + + /* Send the query and return so we can do something else. Needs to be followed by mysql_read_query_result() when we want to @@ -1734,19 +2226,42 @@ mysql_query(MYSQL *mysql, const char *query) */ int STDCALL -mysql_send_query(MYSQL* mysql, const char* query, uint length) +mysql_send_query(MYSQL* mysql, const char* query, ulong length) { - return simple_command(mysql, COM_QUERY, query, length, 1); + DBUG_ENTER("mysql_send_query"); + DBUG_PRINT("enter",("rpl_parse: %d rpl_pivot: %d", + mysql->options.rpl_parse, mysql->rpl_pivot)); + + 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; + DBUG_RETURN(simple_command(mysql, COM_QUERY, query, length, 1)); } + int STDCALL mysql_read_query_result(MYSQL *mysql) { uchar *pos; ulong field_count; MYSQL_DATA *fields; - uint length; + ulong length; DBUG_ENTER("mysql_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 = net_safe_read(mysql)) == packet_error) DBUG_RETURN(-1); free_old_query(mysql); /* Free old result */ @@ -1783,80 +2298,86 @@ get_info: CLIENT_LONG_FLAG)))) DBUG_RETURN(-1); mysql->status=MYSQL_STATUS_GET_RESULT; - mysql->field_count=field_count; + mysql->field_count= (uint) field_count; DBUG_RETURN(0); } + int STDCALL -mysql_real_query(MYSQL *mysql, const char *query, uint length) +mysql_real_query(MYSQL *mysql, const char *query, ulong length) { DBUG_ENTER("mysql_real_query"); DBUG_PRINT("enter",("handle: %lx",mysql)); - DBUG_PRINT("query",("Query = \"%s\"",query)); - if (simple_command(mysql,COM_QUERY,query,length,1)) + DBUG_PRINT("query",("Query = '%-.4096s'",query)); + + if (mysql_send_query(mysql,query,length)) DBUG_RETURN(-1); DBUG_RETURN(mysql_read_query_result(mysql)); } + static int send_file_to_server(MYSQL *mysql, const char *filename) { - int fd, readcount; - char buf[IO_SIZE*15],*tmp_name; + int fd, readcount, result= -1; + uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE); + char *buf, tmp_name[FN_REFLEN]; DBUG_ENTER("send_file_to_server"); - fn_format(buf,filename,"","",4); /* Convert to client format */ - if (!(tmp_name=my_strdup(buf,MYF(0)))) + if (!(buf=my_malloc(packet_length,MYF(0)))) { strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY)); DBUG_RETURN(-1); } + + fn_format(tmp_name,filename,"","",4); /* Convert to client format */ if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0) { + my_net_write(&mysql->net,"",0); /* Server needs one packet */ + net_flush(&mysql->net); mysql->net.last_errno=EE_FILENOTFOUND; - sprintf(buf,EE(mysql->net.last_errno),tmp_name,errno); - strmake(mysql->net.last_error,buf,sizeof(mysql->net.last_error)-1); - my_net_write(&mysql->net,"",0); net_flush(&mysql->net); - my_free(tmp_name,MYF(0)); - DBUG_RETURN(-1); + my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, + EE(mysql->net.last_errno),tmp_name, errno); + goto err; } - while ((readcount = (int) my_read(fd,buf,sizeof(buf),MYF(0))) > 0) + while ((readcount = (int) my_read(fd,(byte*) buf,packet_length,MYF(0))) > 0) { if (my_net_write(&mysql->net,buf,readcount)) { + DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file")); mysql->net.last_errno=CR_SERVER_LOST; strmov(mysql->net.last_error,ER(mysql->net.last_errno)); - DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file")); - (void) my_close(fd,MYF(0)); - my_free(tmp_name,MYF(0)); - DBUG_RETURN(-1); + goto err; } } - (void) my_close(fd,MYF(0)); /* Send empty packet to mark end of file */ if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net)) { mysql->net.last_errno=CR_SERVER_LOST; - sprintf(mysql->net.last_error,ER(mysql->net.last_errno),socket_errno); - my_free(tmp_name,MYF(0)); - DBUG_RETURN(-1); + sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno); + goto err; } if (readcount < 0) { mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */ - sprintf(buf,EE(mysql->net.last_errno),tmp_name,errno); - strmake(mysql->net.last_error,buf,sizeof(mysql->net.last_error)-1); - my_free(tmp_name,MYF(0)); - DBUG_RETURN(-1); + my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, + tmp_name,errno); + goto err; } - DBUG_RETURN(0); + result=0; /* Ok */ + +err: + if (fd >= 0) + (void) my_close(fd,MYF(0)); + my_free(buf,MYF(0)); + DBUG_RETURN(result); } /************************************************************************** -** Alloc result struct for buffered results. All rows are read to buffer. -** mysql_data_seek may be used. + Alloc result struct for buffered results. All rows are read to buffer. + mysql_data_seek may be used. **************************************************************************/ MYSQL_RES * STDCALL @@ -1865,6 +2386,9 @@ 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) @@ -1874,8 +2398,9 @@ mysql_store_result(MYSQL *mysql) DBUG_RETURN(0); } mysql->status=MYSQL_STATUS_READY; /* server is ready */ - if (!(result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+ - sizeof(ulong)*mysql->field_count, + if (!(result=(MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+ + sizeof(ulong) * + mysql->field_count), MYF(MY_WME | MY_ZEROFILL)))) { mysql->net.last_errno=CR_OUT_OF_MEMORY; @@ -1902,13 +2427,13 @@ mysql_store_result(MYSQL *mysql) /************************************************************************** -** Alloc struct for use with unbuffered reads. Data is fetched by domand -** when calling to mysql_fetch_row. -** mysql_data_seek is a noop. -** -** No other queries may be specified with the same MYSQL handle. -** There shouldn't be much processing per row because mysql server shouldn't -** have to wait for the client (and will not wait more than 30 sec/packet). + Alloc struct for use with unbuffered reads. Data is fetched by domand + when calling to mysql_fetch_row. + mysql_data_seek is a noop. + + No other queries may be specified with the same MYSQL handle. + There shouldn't be much processing per row because mysql server shouldn't + have to wait for the client (and will not wait more than 30 sec/packet). **************************************************************************/ MYSQL_RES * STDCALL @@ -1917,6 +2442,8 @@ mysql_use_result(MYSQL *mysql) MYSQL_RES *result; DBUG_ENTER("mysql_use_result"); + mysql = mysql->last_used_con; + if (!mysql->fields) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) @@ -1950,7 +2477,7 @@ mysql_use_result(MYSQL *mysql) /************************************************************************** -** Return next field of the query results + Return next field of the query results **************************************************************************/ MYSQL_FIELD * STDCALL @@ -1963,7 +2490,7 @@ mysql_fetch_field(MYSQL_RES *result) /************************************************************************** -** Return next row of the query results + Return next row of the query results **************************************************************************/ MYSQL_ROW STDCALL @@ -2004,9 +2531,9 @@ mysql_fetch_row(MYSQL_RES *res) } /************************************************************************** -** Get column lengths of the current row -** If one uses mysql_use_result, res->lengths contains the length information, -** else the lengths are calculated from the offset between pointers. + Get column lengths of the current row + If one uses mysql_use_result, res->lengths contains the length information, + else the lengths are calculated from the offset between pointers. **************************************************************************/ ulong * STDCALL @@ -2031,7 +2558,7 @@ mysql_fetch_lengths(MYSQL_RES *res) continue; } if (start) /* Found end of prev string */ - *prev_length= (uint) (*column-start-1); + *prev_length= (ulong) (*column-start-1); start= *column; prev_length=lengths; } @@ -2040,7 +2567,7 @@ mysql_fetch_lengths(MYSQL_RES *res) } /************************************************************************** -** Move to a specific row and column + Move to a specific row and column **************************************************************************/ void STDCALL @@ -2055,9 +2582,9 @@ mysql_data_seek(MYSQL_RES *result, my_ulonglong row) } /************************************************************************* -** put the row or field cursor one a position one got from mysql_row_tell() -** This doesn't restore any data. The next mysql_fetch_row or -** mysql_fetch_field will return the next row or field after the last used + put the row or field cursor one a position one got from mysql_row_tell() + This doesn't restore any data. The next mysql_fetch_row or + mysql_fetch_field will return the next row or field after the last used *************************************************************************/ MYSQL_ROW_OFFSET STDCALL @@ -2079,7 +2606,7 @@ mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET field_offset) } /***************************************************************************** -** List all databases + List all databases *****************************************************************************/ MYSQL_RES * STDCALL @@ -2096,8 +2623,8 @@ mysql_list_dbs(MYSQL *mysql, const char *wild) /***************************************************************************** -** List all tables in a database -** If wild is given then only the tables matching wild is returned + List all tables in a database + If wild is given then only the tables matching wild is returned *****************************************************************************/ MYSQL_RES * STDCALL @@ -2114,10 +2641,10 @@ mysql_list_tables(MYSQL *mysql, const char *wild) /************************************************************************** -** List all fields in a table -** If wild is given then only the fields matching wild is returned -** Instead of this use query: -** show fields in 'table' like "wild" + List all fields in a table + If wild is given then only the fields matching wild is returned + Instead of this use query: + show fields in 'table' like "wild" **************************************************************************/ MYSQL_RES * STDCALL @@ -2132,7 +2659,7 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild) LINT_INIT(query); end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128); - if (simple_command(mysql,COM_FIELD_LIST,buff,(uint) (end-buff),1) || + if (simple_command(mysql,COM_FIELD_LIST,buff,(ulong) (end-buff),1) || !(query = read_rows(mysql,(MYSQL_FIELD*) 0,6))) DBUG_RETURN(NULL); @@ -2182,12 +2709,13 @@ mysql_list_processes(MYSQL *mysql) } +#ifdef USE_OLD_FUNCTIONS int STDCALL mysql_create_db(MYSQL *mysql, const char *db) { DBUG_ENTER("mysql_createdb"); DBUG_PRINT("enter",("db: %s",db)); - DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (uint) strlen(db),0)); + DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (ulong) strlen(db),0)); } @@ -2196,8 +2724,9 @@ mysql_drop_db(MYSQL *mysql, const char *db) { DBUG_ENTER("mysql_drop_db"); DBUG_PRINT("enter",("db: %s",db)); - DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(uint) strlen(db),0)); + DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(ulong) strlen(db),0)); } +#endif int STDCALL @@ -2234,7 +2763,7 @@ mysql_dump_debug_info(MYSQL *mysql) DBUG_RETURN(simple_command(mysql,COM_DEBUG,0,0,0)); } -char * STDCALL +const char * STDCALL mysql_stat(MYSQL *mysql) { DBUG_ENTER("mysql_stat"); @@ -2259,14 +2788,14 @@ mysql_ping(MYSQL *mysql) } -char * STDCALL +const char * STDCALL mysql_get_server_info(MYSQL *mysql) { return((char*) mysql->server_version); } -char * STDCALL +const char * STDCALL mysql_get_host_info(MYSQL *mysql) { return(mysql->host_info); @@ -2279,7 +2808,7 @@ mysql_get_proto_info(MYSQL *mysql) return (mysql->protocol_version); } -char * STDCALL +const char * STDCALL mysql_get_client_info(void) { return (char*) MYSQL_SERVER_VERSION; @@ -2334,8 +2863,8 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) } /**************************************************************************** -** Functions to get information from the MySQL structure -** These are functions to make shared libraries more usable. + Functions to get information from the MySQL structure + These are functions to make shared libraries more usable. ****************************************************************************/ /* MYSQL_RES */ @@ -2364,12 +2893,12 @@ MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res) return (res)->fields; } -MYSQL_ROWS * STDCALL mysql_row_tell(MYSQL_RES *res) +MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res) { return res->data_cursor; } -uint STDCALL mysql_field_tell(MYSQL_RES *res) +MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res) { return (res)->current_field; } @@ -2378,32 +2907,32 @@ uint STDCALL mysql_field_tell(MYSQL_RES *res) unsigned int STDCALL mysql_field_count(MYSQL *mysql) { - return mysql->field_count; + return mysql->last_used_con->field_count; } my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql) { - return (mysql)->affected_rows; + return mysql->last_used_con->affected_rows; } my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql) { - return (mysql)->insert_id; + return mysql->last_used_con->insert_id; } uint STDCALL mysql_errno(MYSQL *mysql) { - return (mysql)->net.last_errno; + return mysql->net.last_errno; } -char * STDCALL mysql_error(MYSQL *mysql) +const char * STDCALL mysql_error(MYSQL *mysql) { - return (mysql)->net.last_error; + return mysql->net.last_error; } -char *STDCALL mysql_info(MYSQL *mysql) +const char *STDCALL mysql_info(MYSQL *mysql) { - return (mysql)->info; + return mysql->info; } ulong STDCALL mysql_thread_id(MYSQL *mysql) @@ -2427,13 +2956,26 @@ uint STDCALL mysql_thread_safe(void) } /**************************************************************************** -** Some support functions + Some support functions ****************************************************************************/ /* -** Add escape characters to a string (blob?) to make it suitable for a insert -** to should at least have place for length*2+1 chars -** Returns the length of the to string + Functions called my my_net_init() to set some application specific variables +*/ + +void my_net_local_init(NET *net) +{ + net->max_packet= (uint) net_buffer_length; + net->read_timeout= (uint) net_read_timeout; + net->write_timeout=(uint) net_write_timeout; + net->retry_count= 1; + net->max_packet_size= max(net_buffer_length, max_allowed_packet); +} + +/* + Add escape characters to a string (blob?) to make it suitable for a insert + to should at least have place for length*2+1 chars + Returns the length of the to string */ ulong STDCALL diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def new file mode 100644 index 00000000000..7f4edb445e1 --- /dev/null +++ b/libmysql/libmysql.def @@ -0,0 +1,124 @@ +LIBRARY LIBMYSQL +DESCRIPTION 'MySQL 4.0 Client Library' +VERSION 5.0 +EXPORTS + mysql_affected_rows + mysql_close + mysql_data_seek + mysql_debug + mysql_dump_debug_info + mysql_eof + mysql_errno + mysql_error + mysql_escape_string + mysql_fetch_field + mysql_fetch_field_direct + mysql_fetch_fields + mysql_fetch_lengths + mysql_fetch_row + mysql_field_count + mysql_field_seek + mysql_field_tell + mysql_free_result + mysql_get_client_info + mysql_get_host_info + mysql_get_proto_info + mysql_get_server_info + mysql_info + mysql_init + mysql_insert_id + mysql_kill + mysql_list_dbs + mysql_list_fields + mysql_list_processes + mysql_list_tables + mysql_num_fields + mysql_num_rows + mysql_odbc_escape_string + mysql_options + mysql_ping + mysql_query + mysql_real_connect + mysql_real_query + mysql_refresh + mysql_row_seek + mysql_row_tell + mysql_select_db + mysql_shutdown + mysql_stat + mysql_store_result + mysql_thread_id + mysql_use_result + bmove_upp + delete_dynamic + _dig_vec + init_dynamic_array + insert_dynamic + int2str + is_prefix + list_add + list_delete + max_allowed_packet + my_casecmp + my_init + my_end + my_strdup + my_malloc + my_memdup + my_no_flags_free + my_realloc + my_thread_end + my_thread_init + net_buffer_length + set_dynamic + strcend + strdup_root + strfill + strinstr + strmake + strmov + strxmov + myodbc_remove_escape + mysql_thread_safe + mysql_character_set_name + mysql_change_user + mysql_send_query + mysql_read_query_result + mysql_real_escape_string + mysql_ssl_set + mysql_real_connect + mysql_master_query + mysql_master_send_query + mysql_slave_query + mysql_slave_send_query + mysql_enable_rpl_parse + mysql_disable_rpl_parse + mysql_rpl_parse_enabled + mysql_enable_reads_from_master + mysql_disable_reads_from_master + mysql_reads_from_master_enabled + mysql_rpl_query_type + mysql_rpl_probe + mysql_set_master + mysql_add_slave + my_getopt_print_errors + handle_options + my_print_help + my_print_variables + getopt_ull_limit_value + getopt_compare_strings + + + + + + + + + + + + + + + diff --git a/libmysql/manager.c b/libmysql/manager.c new file mode 100644 index 00000000000..22b109caea8 --- /dev/null +++ b/libmysql/manager.c @@ -0,0 +1,264 @@ +/* Copyright (C) 2000 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; either version 2 of the License, or + (at your option) any later version. + + 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 */ + +#include <my_global.h> +#if defined(THREAD) +#include <my_pthread.h> /* because of signal() */ +#endif +#include "mysql.h" +#include "mysql_version.h" +#include "mysqld_error.h" +#include <my_sys.h> +#include <mysys_err.h> +#include <m_string.h> +#include <m_ctype.h> +#include <my_net.h> +#include <errmsg.h> +#include <violite.h> +#include <sys/stat.h> +#include <signal.h> +#include <errno.h> + +#if defined(OS2) +# include <sys/un.h> +#elif !defined( __WIN__) +#include <sys/resource.h> +#ifdef HAVE_SYS_UN_H +# include <sys/un.h> +#endif +#include <netdb.h> +#ifdef HAVE_SELECT_H +# include <select.h> +#endif +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +#include <sys/utsname.h> +#endif /* __WIN__ */ + +#ifndef INADDR_NONE +#define INADDR_NONE -1 +#endif + +#define RES_BUF_SHIFT 5 +#define NET_BUF_SIZE 2048 + +MYSQL_MANAGER* STDCALL mysql_manager_init(MYSQL_MANAGER* con) +{ + int net_buf_size=NET_BUF_SIZE; + if (!con) + { + if (!(con=(MYSQL_MANAGER*)my_malloc(sizeof(*con)+net_buf_size, + MYF(MY_WME|MY_ZEROFILL)))) + return 0; + con->free_me=1; + con->net_buf=(char*)con+sizeof(*con); + } + else + { + bzero((char*)con,sizeof(*con)); + if (!(con->net_buf=my_malloc(net_buf_size,MYF(0)))) + return 0; + } + con->net_buf_pos=con->net_data_end=con->net_buf; + con->net_buf_size=net_buf_size; + return con; +} + +MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con, + const char* host, + const char* user, + const char* passwd, + unsigned int port) +{ + my_socket sock; + struct sockaddr_in sock_addr; + uint32 ip_addr; + char msg_buf[MAX_MYSQL_MANAGER_MSG]; + int msg_len; + Vio* vio; + my_bool not_used; + + if (!host) + host="localhost"; + if (!user) + user="root"; + if (!passwd) + passwd=""; + + if ((sock=(my_socket)socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET) + { + con->last_errno=errno; + strmov(con->last_error,"Cannot create socket"); + goto err; + } + if (!(vio=vio_new(sock,VIO_TYPE_TCPIP,FALSE))) + { + con->last_errno=ENOMEM; + strmov(con->last_error,"Cannot create network I/O object"); + goto err; + } + vio_blocking(vio, TRUE, ¬_used); + my_net_init(&con->net,vio); + bzero((char*) &sock_addr,sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) + { + memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); + } + else + { + int tmp_errno; + struct hostent tmp_hostent,*hp; + char buff2[GETHOSTBYNAME_BUFF_SIZE]; + hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2), + &tmp_errno); + if (!hp) + { + con->last_errno=tmp_errno; + sprintf(con->last_error,"Could not resolve host '%s'",host); + my_gethostbyname_r_free(); + goto err; + } + memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length); + my_gethostbyname_r_free(); + } + sock_addr.sin_port = (ushort) htons((ushort) port); + if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), + 0) <0) + { + con->last_errno=errno; + sprintf(con->last_error ,"Could not connect to %-.64s", host); + goto err; + } + /* read the greating */ + if (my_net_read(&con->net) == packet_error) + { + con->last_errno=errno; + strmov(con->last_error,"Read error on socket"); + goto err; + } + sprintf(msg_buf,"%-.16s %-.16s\n",user,passwd); + msg_len=strlen(msg_buf); + if (my_net_write(&con->net,msg_buf,msg_len) || net_flush(&con->net)) + { + con->last_errno=con->net.last_errno; + strmov(con->last_error,"Write error on socket"); + goto err; + } + if (my_net_read(&con->net) == packet_error) + { + con->last_errno=errno; + strmov(con->last_error,"Read error on socket"); + goto err; + } + if ((con->cmd_status=atoi((char*) con->net.read_pos)) != MANAGER_OK) + { + strmov(con->last_error,"Access denied"); + goto err; + } + if (!my_multi_malloc(MYF(0), &con->host, (uint)strlen(host)+1, + &con->user, (uint)strlen(user)+1, + &con->passwd, (uint)strlen(passwd)+1, + NullS)) + { + con->last_errno=ENOMEM; + strmov(con->last_error,"Out of memory"); + goto err; + } + strmov(con->host,host); + strmov(con->user,user); + strmov(con->passwd,passwd); + return con; + +err: + { + my_bool free_me=con->free_me; + con->free_me=0; + mysql_manager_close(con); + con->free_me=free_me; + } + return 0; +} + +void STDCALL mysql_manager_close(MYSQL_MANAGER* con) +{ + /* + No need to free con->user and con->passwd, because they were + allocated in my_multimalloc() along with con->host, freeing + con->hosts frees the whole block + */ + my_free((gptr)con->host,MYF(MY_ALLOW_ZERO_PTR)); + net_end(&con->net); + if (con->free_me) + my_free((gptr)con,MYF(0)); +} + + +int STDCALL mysql_manager_command(MYSQL_MANAGER* con,const char* cmd, + int cmd_len) +{ + if (!cmd_len) + cmd_len=strlen(cmd); + if (my_net_write(&con->net,(char*)cmd,cmd_len) || net_flush(&con->net)) + { + con->last_errno=errno; + strmov(con->last_error,"Write error on socket"); + return 1; + } + con->eof=0; + return 0; +} + + +int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con, char* res_buf, + int res_buf_size) +{ + char* res_buf_end=res_buf+res_buf_size; + char* net_buf=(char*) con->net.read_pos, *net_buf_end; + int res_buf_shift=RES_BUF_SHIFT; + uint num_bytes; + + if (res_buf_size<RES_BUF_SHIFT) + { + con->last_errno=ENOMEM; + strmov(con->last_error,"Result buffer too small"); + return 1; + } + + if ((num_bytes=my_net_read(&con->net)) == packet_error) + { + con->last_errno=errno; + strmov(con->last_error,"socket read failed"); + return 1; + } + + net_buf_end=net_buf+num_bytes; + + if ((con->eof=(net_buf[3]==' '))) + res_buf_shift--; + net_buf+=res_buf_shift; + res_buf_end[-1]=0; + for (;net_buf<net_buf_end && res_buf < res_buf_end;res_buf++,net_buf++) + { + if ((*res_buf=*net_buf) == '\r') + { + *res_buf=0; + break; + } + } + return 0; +} diff --git a/libmysql/net.c b/libmysql/net.c deleted file mode 100644 index 24e4da3561a..00000000000 --- a/libmysql/net.c +++ /dev/null @@ -1,685 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/* Write and read of logical packets to/from socket -** Writes are cached into net_buffer_length big packets. -** Read packets are reallocated dynamicly when reading big packets. -** Each logical packet has the following pre-info: -** 3 byte length & 1 byte package-number. -*/ - -#ifdef __WIN__ -#include <winsock.h> -#endif -#include <global.h> -#include <violite.h> -#include <my_sys.h> -#include <m_string.h> -#include "mysql.h" -#include "mysqld_error.h" -#include <signal.h> -#include <errno.h> -#include <sys/types.h> -#include <violite.h> - -#ifdef MYSQL_SERVER -ulong max_allowed_packet=65536; -extern ulong net_read_timeout,net_write_timeout; -extern uint test_flags; -#else -ulong max_allowed_packet=16*1024*1024L; -ulong net_read_timeout= NET_READ_TIMEOUT; -ulong net_write_timeout= NET_WRITE_TIMEOUT; -#endif -ulong net_buffer_length=8192; /* Default length. Enlarged if necessary */ - -#if !defined(__WIN__) && !defined(MSDOS) -#include <sys/socket.h> -#else -#undef MYSQL_SERVER /* Win32 can't handle interrupts */ -#endif -#if !defined(MSDOS) && !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__) -#include <netinet/in_systm.h> -#include <netinet/in.h> -#include <netinet/ip.h> -#if !defined(alpha_linux_port) -#include <netinet/tcp.h> -#endif -#endif -#include "mysqld_error.h" -#ifdef MYSQL_SERVER -#include "my_pthread.h" -#include "thr_alarm.h" -void sql_print_error(const char *format,...); -#define RETRY_COUNT mysqld_net_retry_count -extern ulong mysqld_net_retry_count; -#else - -#ifdef OS2 /* avoid name conflict */ -#define thr_alarm_t thr_alarm_t_net -#define ALARM ALARM_net -#endif - -typedef my_bool thr_alarm_t; -typedef my_bool ALARM; -#define thr_alarm_init(A) (*(A))=0 -#define thr_alarm_in_use(A) (*(A)!= 0) -#define thr_end_alarm(A) -#define thr_alarm(A,B,C) local_thr_alarm((A),(B),(C)) -inline int local_thr_alarm(my_bool *A,int B __attribute__((unused)),ALARM *C __attribute__((unused))) -{ - *A=1; - return 0; -} -#define thr_got_alarm(A) 0 -#define RETRY_COUNT 1 -#endif - -#ifdef MYSQL_SERVER -extern ulong bytes_sent, bytes_received; -extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received; -#else -#undef statistic_add -#define statistic_add(A,B,C) -#endif - -/* -** Give error if a too big packet is found -** The server can change this with the -O switch, but because the client -** can't normally do this the client should have a bigger max-buffer. -*/ - -#define TEST_BLOCKING 8 -static int net_write_buff(NET *net,const char *packet,uint len); - - - /* Init with packet info */ - -int my_net_init(NET *net, Vio* vio) -{ - if (!(net->buff=(uchar*) my_malloc(net_buffer_length,MYF(MY_WME)))) - return 1; - if (net_buffer_length > max_allowed_packet) - max_allowed_packet=net_buffer_length; - net->buff_end=net->buff+(net->max_packet=net_buffer_length); - net->vio = vio; - net->no_send_ok = 0; - net->error=0; net->return_errno=0; net->return_status=0; - net->timeout=(uint) net_read_timeout; /* Timeout for read */ - net->pkt_nr=0; - net->write_pos=net->read_pos = net->buff; - net->last_error[0]=0; - net->compress=0; net->reading_or_writing=0; - net->where_b = net->remain_in_buf=0; - net->last_errno=0; - - if (vio != 0) /* If real connection */ - { - net->fd = vio_fd(vio); /* For perl DBI/DBD */ -#if defined(MYSQL_SERVER) && !defined(___WIN__) && !defined(__EMX__) && !defined(OS2) - if (!(test_flags & TEST_BLOCKING)) - vio_blocking(vio, FALSE); -#endif - vio_fastsend(vio); - } - return 0; -} - -void net_end(NET *net) -{ - my_free((gptr) net->buff,MYF(MY_ALLOW_ZERO_PTR)); - net->buff=0; -} - -/* Realloc the packet buffer */ - -static my_bool net_realloc(NET *net, ulong length) -{ - uchar *buff; - ulong pkt_length; - if (length >= max_allowed_packet) - { - DBUG_PRINT("error",("Packet too large (%lu)", length)); - net->error=1; - net->last_errno=ER_NET_PACKET_TOO_LARGE; - return 1; - } - pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1); - if (!(buff=(uchar*) my_realloc((char*) net->buff, pkt_length, MYF(MY_WME)))) - { - net->error=1; -#ifdef MYSQL_SERVER - net->last_errno=ER_OUT_OF_RESOURCES; -#endif - return 1; - } - net->buff=net->write_pos=buff; - net->buff_end=buff+(net->max_packet=pkt_length); - return 0; -} - - /* Remove unwanted characters from connection */ - -void net_clear(NET *net) -{ -#ifndef EXTRA_DEBUG - int count; - bool is_blocking=vio_is_blocking(net->vio); - if (is_blocking) - vio_blocking(net->vio, FALSE); - if (!vio_is_blocking(net->vio)) /* Safety if SSL */ - { - while ( (count = vio_read(net->vio, (char*) (net->buff), - net->max_packet)) > 0) - DBUG_PRINT("info",("skipped %d bytes from file: %s", - count,vio_description(net->vio))); - if (is_blocking) - vio_blocking(net->vio, TRUE); - } -#endif /* EXTRA_DEBUG */ - net->pkt_nr=0; /* Ready for new command */ - net->write_pos=net->buff; -} - - /* Flush write_buffer if not empty. */ - -int net_flush(NET *net) -{ - int error=0; - DBUG_ENTER("net_flush"); - if (net->buff != net->write_pos) - { - error=net_real_write(net,(char*) net->buff, - (uint) (net->write_pos - net->buff)); - net->write_pos=net->buff; - } - DBUG_RETURN(error); -} - - -/***************************************************************************** -** Write something to server/client buffer -*****************************************************************************/ - - -/* -** Write a logical packet with packet header -** Format: Packet length (3 bytes), packet number(1 byte) -** When compression is used a 3 byte compression length is added -** NOTE: If compression is used the original package is destroyed! -*/ - -int -my_net_write(NET *net,const char *packet,ulong len) -{ - uchar buff[NET_HEADER_SIZE]; - int3store(buff,len); - buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); - if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE)) - return 1; - return net_write_buff(net,packet,len); -} - -int -net_write_command(NET *net,uchar command,const char *packet,ulong len) -{ - uchar buff[NET_HEADER_SIZE+1]; - uint length=len+1; /* 1 extra byte for command */ - - int3store(buff,length); - buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); - buff[4]=command; - if (net_write_buff(net,(char*) buff,5)) - return 1; - return test(net_write_buff(net,packet,len) || net_flush(net)); -} - - -static int -net_write_buff(NET *net,const char *packet,uint len) -{ - uint left_length=(uint) (net->buff_end - net->write_pos); - - while (len > left_length) - { - memcpy((char*) net->write_pos,packet,left_length); - if (net_real_write(net,(char*) net->buff,net->max_packet)) - return 1; - net->write_pos=net->buff; - packet+=left_length; - len-=left_length; - left_length=net->max_packet; - } - memcpy((char*) net->write_pos,packet,len); - net->write_pos+=len; - return 0; -} - -/* Read and write using timeouts */ - -int -net_real_write(NET *net,const char *packet,ulong len) -{ - int length; - char *pos,*end; - thr_alarm_t alarmed; -#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) - ALARM alarm_buff; -#endif - uint retry_count=0; - my_bool net_blocking = vio_is_blocking(net->vio); - DBUG_ENTER("net_real_write"); - - if (net->error == 2) - DBUG_RETURN(-1); /* socket can't be used */ - - net->reading_or_writing=2; -#ifdef HAVE_COMPRESS - if (net->compress) - { - ulong complen; - uchar *b; - uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE; - if (!(b=(uchar*) my_malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE, - MYF(MY_WME)))) - { -#ifdef MYSQL_SERVER - net->last_errno=ER_OUT_OF_RESOURCES; - net->error=2; -#endif - net->reading_or_writing=0; - DBUG_RETURN(1); - } - memcpy(b+header_length,packet,len); - - if (my_compress((byte*) b+header_length,&len,&complen)) - { - DBUG_PRINT("warning", - ("Compression error; Continuing without compression")); - complen=0; - } - int3store(&b[NET_HEADER_SIZE],complen); - int3store(b,len); - b[3]=(uchar) (net->pkt_nr++); - len+= header_length; - packet= (char*) b; - } -#endif /* HAVE_COMPRESS */ - - /* DBUG_DUMP("net",packet,len); */ -#ifdef MYSQL_SERVER - thr_alarm_init(&alarmed); - if (net_blocking) - thr_alarm(&alarmed,(uint) net_write_timeout,&alarm_buff); -#else - alarmed=0; -#endif /* MYSQL_SERVER */ - - pos=(char*) packet; end=pos+len; - while (pos != end) - { - if ((int) (length=vio_write(net->vio,pos,(int) (end-pos))) <= 0) - { - my_bool interrupted = vio_should_retry(net->vio); -#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2)) - if ((interrupted || length==0) && !thr_alarm_in_use(&alarmed)) - { - if (!thr_alarm(&alarmed,(uint) net_write_timeout,&alarm_buff)) - { /* Always true for client */ - if (!vio_is_blocking(net->vio)) - { - while (vio_blocking(net->vio, TRUE) < 0) - { - if (vio_should_retry(net->vio) && retry_count++ < RETRY_COUNT) - continue; -#ifdef EXTRA_DEBUG - fprintf(stderr, - "%s: my_net_write: fcntl returned error %d, aborting thread\n", - my_progname,vio_errno(net->vio)); -#endif /* EXTRA_DEBUG */ - net->error=2; /* Close socket */ - goto end; - } - } - retry_count=0; - continue; - } - } - else -#endif /* (!defined(__WIN__) && !defined(__EMX__)) */ - if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) && - interrupted) - { - if (retry_count++ < RETRY_COUNT) - continue; -#ifdef EXTRA_DEBUG - fprintf(stderr, "%s: write looped, aborting thread\n", - my_progname); -#endif /* EXTRA_DEBUG */ - } -#if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) - if (vio_errno(net->vio) == SOCKET_EINTR) - { - DBUG_PRINT("warning",("Interrupted write. Retrying...")); - continue; - } -#endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */ - net->error=2; /* Close socket */ -#ifdef MYSQL_SERVER - net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED : - ER_NET_ERROR_ON_WRITE); -#endif /* MYSQL_SERVER */ - break; - } - pos+=length; - statistic_add(bytes_sent,length,&LOCK_bytes_sent); - } -#ifndef __WIN__ - end: -#endif -#ifdef HAVE_COMPRESS - if (net->compress) - my_free((char*) packet,MYF(0)); -#endif - if (thr_alarm_in_use(&alarmed)) - { - thr_end_alarm(&alarmed); - vio_blocking(net->vio, net_blocking); - } - net->reading_or_writing=0; - DBUG_RETURN(((int) (pos != end))); -} - - -/***************************************************************************** -** Read something from server/clinet -*****************************************************************************/ - -#ifdef MYSQL_SERVER - -/* - Help function to clear the commuication buffer when we get a too - big packet -*/ - -static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed) -{ - ALARM alarm_buff; - uint retry_count=0; - if (!thr_alarm_in_use(&alarmed)) - { - if (!thr_alarm(alarmed,net->timeout,&alarm_buff) || - (!vio_is_blocking(net->vio) && vio_blocking(net->vio,TRUE) < 0)) - return; /* Can't setup, abort */ - } - while (remain > 0) - { - ulong length; - if ((int) (length=vio_read(net->vio,(char*) net->buff,remain)) <= 0L) - { - my_bool interrupted = vio_should_retry(net->vio); - if (!thr_got_alarm(alarmed) && interrupted) - { /* Probably in MIT threads */ - if (retry_count++ < RETRY_COUNT) - continue; - } - return; - } - remain -=(ulong) length; - statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received); - } -} -#endif /* MYSQL_SERVER */ - - -static uint -my_real_read(NET *net, ulong *complen) -{ - uchar *pos; - long length; - uint i,retry_count=0; - ulong len=packet_error; - thr_alarm_t alarmed; -#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2)) || defined(MYSQL_SERVER) - ALARM alarm_buff; -#endif - my_bool net_blocking=vio_is_blocking(net->vio); - ulong remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE : - NET_HEADER_SIZE); - *complen = 0; - - net->reading_or_writing=1; - thr_alarm_init(&alarmed); -#ifdef MYSQL_SERVER - if (net_blocking) - thr_alarm(&alarmed,net->timeout,&alarm_buff); -#endif /* MYSQL_SERVER */ - - pos = net->buff + net->where_b; /* net->packet -4 */ - for (i=0 ; i < 2 ; i++) - { - while (remain > 0) - { - /* First read is done with non blocking mode */ - if ((int) (length=vio_read(net->vio,(char*) pos,remain)) <= 0L) - { - my_bool interrupted = vio_should_retry(net->vio); - - DBUG_PRINT("info",("vio_read returned %d, errno: %d", - length, vio_errno(net->vio))); -#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2)) || defined(MYSQL_SERVER) - /* - We got an error that there was no data on the socket. We now set up - an alarm to not 'read forever', change the socket to non blocking - mode and try again - */ - if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed)) - { - if (!thr_alarm(&alarmed,net->timeout,&alarm_buff)) /* Don't wait too long */ - { - if (!vio_is_blocking(net->vio)) - { - while (vio_blocking(net->vio,TRUE) < 0) - { - if (vio_should_retry(net->vio) && - retry_count++ < RETRY_COUNT) - continue; - DBUG_PRINT("error", - ("fcntl returned error %d, aborting thread", - vio_errno(net->vio))); -#ifdef EXTRA_DEBUG - fprintf(stderr, - "%s: read: fcntl returned error %d, aborting thread\n", - my_progname,vio_errno(net->vio)); -#endif /* EXTRA_DEBUG */ - len= packet_error; - net->error=2; /* Close socket */ -#ifdef MYSQL_SERVER - net->last_errno=ER_NET_FCNTL_ERROR; -#endif - goto end; - } - } - retry_count=0; - continue; - } - } -#endif /* (!defined(__WIN__) && !defined(__EMX__)) || defined(MYSQL_SERVER) */ - if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) && - interrupted) - { /* Probably in MIT threads */ - if (retry_count++ < RETRY_COUNT) - continue; -#ifdef EXTRA_DEBUG - fprintf(stderr, "%s: read looped with error %d, aborting thread\n", - my_progname,vio_errno(net->vio)); -#endif /* EXTRA_DEBUG */ - } -#if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) - if (vio_should_retry(net->vio)) - { - DBUG_PRINT("warning",("Interrupted read. Retrying...")); - continue; - } -#endif - DBUG_PRINT("error",("Couldn't read packet: remain: %d errno: %d length: %d alarmed: %d", remain,vio_errno(net->vio),length,alarmed)); - len= packet_error; - net->error=2; /* Close socket */ -#ifdef MYSQL_SERVER - net->last_errno= (interrupted ? ER_NET_READ_INTERRUPTED : - ER_NET_READ_ERROR); -#endif - goto end; - } - remain -= (ulong) length; - pos+= (ulong) length; - statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received); - } - if (i == 0) - { /* First parts is packet length */ - ulong helping; - if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr) - { - if (net->buff[net->where_b] != (uchar) 255) - { - DBUG_PRINT("error", - ("Packets out of order (Found: %d, expected %d)", - (int) net->buff[net->where_b + 3], - (uint) (uchar) net->pkt_nr)); -#ifdef EXTRA_DEBUG - fprintf(stderr,"Packets out of order (Found: %d, expected %d)\n", - (int) net->buff[net->where_b + 3], - (uint) (uchar) net->pkt_nr); -#endif - } - len= packet_error; -#ifdef MYSQL_SERVER - net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER; -#endif - goto end; - } - net->pkt_nr++; -#ifdef HAVE_COMPRESS - if (net->compress) - { - /* complen is > 0 if package is really compressed */ - *complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE])); - } -#endif - - len=uint3korr(net->buff+net->where_b); - helping = max(len,*complen) + net->where_b; - /* The necessary size of net->buff */ - if (helping >= net->max_packet) - { - /* We must allocate one extra byte for the end null */ - if (net_realloc(net,helping+1)) - { -#ifdef MYSQL_SERVER - if (i == 1) - my_net_skip_rest(net, len, &alarmed); -#endif - len= packet_error; /* Return error */ - goto end; - } - } - pos=net->buff + net->where_b; - remain = len; - } - } - -end: - if (thr_alarm_in_use(&alarmed)) - { - thr_end_alarm(&alarmed); - vio_blocking(net->vio, net_blocking); - } - net->reading_or_writing=0; - return(len); -} - -uint -my_net_read(NET *net) -{ - ulong len,complen; - -#ifdef HAVE_COMPRESS - if (!net->compress) - { -#endif - len = my_real_read (net,&complen); - net->read_pos = net->buff + net->where_b; - if (len != packet_error) - net->read_pos[len]=0; /* Safeguard for mysql_use_result */ - return len; -#ifdef HAVE_COMPRESS - } - if (net->remain_in_buf) - net->buff[net->buf_length - net->remain_in_buf]=net->save_char; - for (;;) - { - if (net->remain_in_buf) - { - uchar *pos = net->buff + net->buf_length - net->remain_in_buf; - if (net->remain_in_buf >= 4) - { - net->length = uint3korr(pos); - if (net->length <= net->remain_in_buf - 4) - { - /* We have a full packet */ - len=net->length; - net->remain_in_buf -= net->length + 4; - net->read_pos=pos + 4; - break; /* We have a full packet */ - } - } - /* Move data down to read next data packet after current one */ - if (net->buf_length != net->remain_in_buf) - { - memmove(net->buff,pos,net->remain_in_buf); - net->buf_length=net->remain_in_buf; - } - net->where_b=net->buf_length; - } - else - { - net->where_b=0; - net->buf_length=0; - } - - if ((len = my_real_read(net,&complen)) == packet_error) - break; - if (my_uncompress((byte*) net->buff + net->where_b, &len, &complen)) - { - len= packet_error; - net->error=2; /* caller will close socket */ -#ifdef MYSQL_SERVER - net->last_errno=ER_NET_UNCOMPRESS_ERROR; -#endif - break; - } - net->buf_length+=len; - net->remain_in_buf+=len; - } - if (len != packet_error) - { - net->save_char= net->read_pos[len]; /* Must be saved */ - net->read_pos[len]=0; /* Safeguard for mysql_use_result */ - } - return len; -#endif -} diff --git a/libmysql/password.c b/libmysql/password.c index 71ed68c6b2c..1c2c5589215 100644 --- a/libmysql/password.c +++ b/libmysql/password.c @@ -1,19 +1,18 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, +/* Copyright (C) 2000 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; either version 2 of the License, or + (at your option) any later version. + + 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ + 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 */ /* password checking routines */ /***************************************************************************** @@ -35,7 +34,7 @@ This saves a hashed number as a string in the password field. *****************************************************************************/ -#include <global.h> +#include <my_global.h> #include <my_sys.h> #include <m_string.h> #include "mysql.h" diff --git a/libmysql/violite.c b/libmysql/violite.c deleted file mode 100644 index 37fee6fad3d..00000000000 --- a/libmysql/violite.c +++ /dev/null @@ -1,443 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/* - Note that we can't have assertion on file descriptors; The reason for - this is that during mysql shutdown, another thread can close a file - we are working on. In this case we should just return read errors from - the file descriptior. -*/ - -#include <global.h> - -#ifndef HAVE_VIO /* is Vio suppored by the Vio lib ? */ - -#include <errno.h> -#include <assert.h> -#include <violite.h> -#include <my_sys.h> -#include <my_net.h> -#include <m_string.h> -#ifdef HAVE_POLL -#include <sys/poll.h> -#endif -#ifdef HAVE_SYS_IOCTL_H -#include <sys/ioctl.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif - -#if !defined(MSDOS) && !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__) && !defined(__FreeBSD__) -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#if !defined(alpha_linux_port) -#include <netinet/tcp.h> -#endif -#endif - -#if defined(__EMX__) || defined(OS2) -#define ioctlsocket ioctl -#endif /* defined(__EMX__) */ - -#if defined(MSDOS) || defined(__WIN__) -#define O_NONBLOCK 1 /* For emulation of fcntl() */ -#endif -#ifndef EWOULDBLOCK -#define SOCKET_EWOULDBLOCK SOCKET_EAGAIN -#endif - -#ifndef __WIN__ -#define HANDLE void * -#endif - -struct st_vio -{ - my_socket sd; /* my_socket - real or imaginary */ - HANDLE hPipe; - my_bool localhost; /* Are we from localhost? */ - int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */ - struct sockaddr_in local; /* Local internet address */ - struct sockaddr_in remote; /* Remote internet address */ - enum enum_vio_type type; /* Type of connection */ - char desc[30]; /* String description */ -}; - -typedef void *vio_ptr; -typedef char *vio_cstring; - -/* - * Helper to fill most of the Vio* with defaults. - */ - -static void vio_reset(Vio* vio, enum enum_vio_type type, - my_socket sd, HANDLE hPipe, - my_bool localhost) -{ - bzero((char*) vio, sizeof(*vio)); - vio->type = type; - vio->sd = sd; - vio->hPipe = hPipe; - vio->localhost= localhost; -} - -/* Open the socket or TCP/IP connection and read the fnctl() status */ - -Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost) -{ - Vio *vio; - DBUG_ENTER("vio_new"); - DBUG_PRINT("enter", ("sd=%d", sd)); - if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME)))) - { - vio_reset(vio, type, sd, 0, localhost); - sprintf(vio->desc, - (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"), - vio->sd); -#if !defined(___WIN__) && !defined(__EMX__) && !defined(OS2) -#if !defined(NO_FCNTL_NONBLOCK) - vio->fcntl_mode = fcntl(sd, F_GETFL); -#elif defined(HAVE_SYS_IOCTL_H) /* hpux */ - /* Non blocking sockets doesn't work good on HPUX 11.0 */ - (void) ioctl(sd,FIOSNBIO,0); -#endif -#else /* !defined(__WIN__) && !defined(__EMX__) */ - { - /* set to blocking mode by default */ - ulong arg=0, r; - r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg)); - } -#endif - } - DBUG_RETURN(vio); -} - - -#ifdef __WIN__ - -Vio *vio_new_win32pipe(HANDLE hPipe) -{ - Vio *vio; - DBUG_ENTER("vio_new_handle"); - if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME)))) - { - vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE); - strmov(vio->desc, "named pipe"); - } - DBUG_RETURN(vio); -} - -#endif - -void vio_delete(Vio * vio) -{ - /* It must be safe to delete null pointers. */ - /* This matches the semantics of C++'s delete operator. */ - if (vio) - { - if (vio->type != VIO_CLOSED) - vio_close(vio); - my_free((gptr) vio,MYF(0)); - } -} - -int vio_errno(Vio *vio __attribute__((unused))) -{ - return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ -} - - -int vio_read(Vio * vio, gptr buf, int size) -{ - int r; - DBUG_ENTER("vio_read"); - DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size)); -#if defined( __WIN__) || defined(OS2) - if (vio->type == VIO_TYPE_NAMEDPIPE) - { - DWORD length; -#ifdef OS2 - if (!DosRead((HFILE)vio->hPipe, buf, size, &length)) - DBUG_RETURN(-1); -#else - if (!ReadFile(vio->hPipe, buf, size, &length, NULL)) - DBUG_RETURN(-1); -#endif - DBUG_RETURN(length); - } - r = recv(vio->sd, buf, size,0); -#else - errno=0; /* For linux */ - r = read(vio->sd, buf, size); -#endif /* __WIN__ */ -#ifndef DBUG_OFF - if (r < 0) - { - DBUG_PRINT("vio_error", ("Got error %d during read",socket_errno)); - } -#endif /* DBUG_OFF */ - DBUG_PRINT("exit", ("%d", r)); - DBUG_RETURN(r); -} - - -int vio_write(Vio * vio, const gptr buf, int size) -{ - int r; - DBUG_ENTER("vio_write"); - DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size)); -#if defined( __WIN__) || defined(OS2) - if ( vio->type == VIO_TYPE_NAMEDPIPE) - { - DWORD length; -#ifdef OS2 - if (!DosWrite((HFILE)vio->hPipe, (char*) buf, size, &length)) - DBUG_RETURN(-1); -#else - if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL)) - DBUG_RETURN(-1); -#endif - DBUG_RETURN(length); - } - r = send(vio->sd, buf, size,0); -#else - r = write(vio->sd, buf, size); -#endif /* __WIN__ */ -#ifndef DBUG_OFF - if (r < 0) - { - DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno)); - } -#endif /* DBUG_OFF */ - DBUG_PRINT("exit", ("%d", r)); - DBUG_RETURN(r); -} - - -int vio_blocking(Vio * vio, my_bool set_blocking_mode) -{ - int r=0; - DBUG_ENTER("vio_blocking"); - DBUG_PRINT("enter", ("set_blocking_mode: %d", (int) set_blocking_mode)); - -#if !defined(___WIN__) && !defined(__EMX__) && !defined(OS2) -#if !defined(NO_FCNTL_NONBLOCK) - - if (vio->sd >= 0) - { - int old_fcntl=vio->fcntl_mode; - if (set_blocking_mode) - vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */ - else - vio->fcntl_mode |= O_NONBLOCK; /* set bit */ - if (old_fcntl != vio->fcntl_mode) - r = fcntl(vio->sd, F_SETFL, vio->fcntl_mode); - } -#endif /* !defined(NO_FCNTL_NONBLOCK) */ -#else /* !defined(__WIN__) && !defined(__EMX__) */ -#ifndef __EMX__ - if (vio->type != VIO_TYPE_NAMEDPIPE) -#endif - { - ulong arg; - int old_fcntl=vio->fcntl_mode; - if (set_blocking_mode) - { - arg = 0; - vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */ - } - else - { - arg = 1; - vio->fcntl_mode |= O_NONBLOCK; /* set bit */ - } - if (old_fcntl != vio->fcntl_mode) - r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg)); - } -#endif /* !defined(__WIN__) && !defined(__EMX__) */ - DBUG_RETURN(r); -} - -my_bool -vio_is_blocking(Vio * vio) -{ - my_bool r; - DBUG_ENTER("vio_is_blocking"); - r = !(vio->fcntl_mode & O_NONBLOCK); - DBUG_PRINT("exit", ("%d", (int) r)); - DBUG_RETURN(r); -} - - -int vio_fastsend(Vio * vio __attribute__((unused))) -{ - int r=0; - DBUG_ENTER("vio_fastsend"); - -#ifdef IPTOS_THROUGHPUT - { -#ifndef __EMX__ - int tos = IPTOS_THROUGHPUT; - if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos))) -#endif /* !__EMX__ */ - { - int nodelay = 1; - if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay, - sizeof(nodelay))) { - DBUG_PRINT("warning", - ("Couldn't set socket option for fast send")); - r= -1; - } - } - } -#endif /* IPTOS_THROUGHPUT */ - DBUG_PRINT("exit", ("%d", r)); - DBUG_RETURN(r); -} - -int vio_keepalive(Vio* vio, my_bool set_keep_alive) -{ - int r=0; - uint opt = 0; - DBUG_ENTER("vio_keepalive"); - DBUG_PRINT("enter", ("sd=%d set_keep_alive=%d", vio->sd, (int) - set_keep_alive)); - if (vio->type != VIO_TYPE_NAMEDPIPE) - { - if (set_keep_alive) - opt = 1; - r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, - sizeof(opt)); - } - DBUG_RETURN(r); -} - - -my_bool -vio_should_retry(Vio * vio __attribute__((unused))) -{ - int en = socket_errno; - return en == SOCKET_EAGAIN || en == SOCKET_EINTR || en == SOCKET_EWOULDBLOCK; -} - - -int vio_close(Vio * vio) -{ - int r; - DBUG_ENTER("vio_close"); -#ifdef __WIN__ - if (vio->type == VIO_TYPE_NAMEDPIPE) - { -#if defined(__NT__) && defined(MYSQL_SERVER) - CancelIo(vio->hPipe); - DisconnectNamedPipe(vio->hPipe); -#endif - r=CloseHandle(vio->hPipe); - } - else if (vio->type != VIO_CLOSED) -#endif /* __WIN__ */ - { - r=0; - if (shutdown(vio->sd,2)) - r= -1; - if (closesocket(vio->sd)) - r= -1; - } - if (r) - { - DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno)); - /* FIXME: error handling (not critical for MySQL) */ - } - vio->type= VIO_CLOSED; - vio->sd= -1; - DBUG_RETURN(r); -} - - -const char *vio_description(Vio * vio) -{ - return vio->desc; -} - -enum enum_vio_type vio_type(Vio* vio) -{ - return vio->type; -} - -my_socket vio_fd(Vio* vio) -{ - return vio->sd; -} - - -my_bool vio_peer_addr(Vio * vio, char *buf) -{ - DBUG_ENTER("vio_peer_addr"); - DBUG_PRINT("enter", ("sd=%d", vio->sd)); - if (vio->localhost) - { - strmov(buf,"127.0.0.1"); - } - else - { - size_socket addrLen = sizeof(struct sockaddr); - if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)), - &addrLen) != 0) - { - DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno)); - DBUG_RETURN(1); - } - my_inet_ntoa(vio->remote.sin_addr,buf); - } - DBUG_PRINT("exit", ("addr=%s", buf)); - DBUG_RETURN(0); -} - - -void vio_in_addr(Vio *vio, struct in_addr *in) -{ - DBUG_ENTER("vio_in_addr"); - if (vio->localhost) - bzero((char*) in, sizeof(*in)); /* This should never be executed */ - else - *in=vio->remote.sin_addr; - DBUG_VOID_RETURN; -} - - -/* Return 0 if there is data to be read */ - -my_bool vio_poll_read(Vio *vio,uint timeout) -{ -#ifndef HAVE_POLL - return 0; -#else - struct pollfd fds; - int res; - DBUG_ENTER("vio_poll"); - fds.fd=vio->sd; - fds.events=POLLIN; - fds.revents=0; - if ((res=poll(&fds,1,(int) timeout*1000)) <= 0) - { - DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */ - } - DBUG_RETURN(fds.revents & POLLIN ? 0 : 1); -#endif -} - -#endif /* HAVE_VIO */ |