00001 /* Copyright (C) 2000-2003 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 /* 00018 This file is included by both libmysql.c (the MySQL client C API) 00019 and the mysqld server to connect to another MYSQL server. 00020 00021 The differences for the two cases are: 00022 00023 - Things that only works for the client: 00024 - Trying to automaticly determinate user name if not supplied to 00025 mysql_real_connect() 00026 - Support for reading local file with LOAD DATA LOCAL 00027 - SHARED memory handling 00028 - Protection against sigpipe 00029 - Prepared statements 00030 00031 - Things that only works for the server 00032 - Alarm handling on connect 00033 00034 In all other cases, the code should be idential for the client and 00035 server. 00036 */ 00037 00038 #include <my_global.h> 00039 00040 #include "mysql.h" 00041 00042 /* Remove client convenience wrappers */ 00043 #undef max_allowed_packet 00044 #undef net_buffer_length 00045 00046 #ifdef EMBEDDED_LIBRARY 00047 00048 #undef MYSQL_SERVER 00049 00050 #ifndef MYSQL_CLIENT 00051 #define MYSQL_CLIENT 00052 #endif 00053 00054 #define CLI_MYSQL_REAL_CONNECT cli_mysql_real_connect 00055 00056 #undef net_flush 00057 my_bool net_flush(NET *net); 00058 00059 #else /*EMBEDDED_LIBRARY*/ 00060 #define CLI_MYSQL_REAL_CONNECT STDCALL mysql_real_connect 00061 #endif /*EMBEDDED_LIBRARY*/ 00062 #include <my_sys.h> 00063 #include <mysys_err.h> 00064 #include <m_string.h> 00065 #include <m_ctype.h> 00066 #include "mysql_version.h" 00067 #include "mysqld_error.h" 00068 #include "errmsg.h" 00069 #include <violite.h> 00070 #if defined(THREAD) && !defined(__WIN__) 00071 #include <my_pthread.h> /* because of signal() */ 00072 #endif /* defined(THREAD) && !defined(__WIN__) */ 00073 00074 #include <sys/stat.h> 00075 #include <signal.h> 00076 #include <time.h> 00077 #ifdef HAVE_PWD_H 00078 #include <pwd.h> 00079 #endif 00080 #if !defined(MSDOS) && !defined(__WIN__) 00081 #include <sys/socket.h> 00082 #include <netinet/in.h> 00083 #include <arpa/inet.h> 00084 #include <netdb.h> 00085 #ifdef HAVE_SELECT_H 00086 # include <select.h> 00087 #endif 00088 #ifdef HAVE_SYS_SELECT_H 00089 #include <sys/select.h> 00090 #endif 00091 #endif 00092 #ifdef HAVE_SYS_UN_H 00093 # include <sys/un.h> 00094 #endif 00095 00096 #if defined(MSDOS) || defined(__WIN__) 00097 #define perror(A) 00098 #else 00099 #include <errno.h> 00100 #define SOCKET_ERROR -1 00101 #endif 00102 00103 #ifdef __WIN__ 00104 #define CONNECT_TIMEOUT 20 00105 #else 00106 #define CONNECT_TIMEOUT 0 00107 #endif 00108 00109 #include "client_settings.h" 00110 #include <sql_common.h> 00111 00112 uint mysql_port=0; 00113 char *mysql_unix_port= 0; 00114 const char *unknown_sqlstate= "HY000"; 00115 const char *not_error_sqlstate= "00000"; 00116 #ifdef HAVE_SMEM 00117 char *shared_memory_base_name= 0; 00118 const char *def_shared_memory_base_name= default_shared_memory_base_name; 00119 #endif 00120 00121 static void mysql_close_free_options(MYSQL *mysql); 00122 static void mysql_close_free(MYSQL *mysql); 00123 00124 #if !(defined(__WIN__) || defined(__NETWARE__)) 00125 static int wait_for_data(my_socket fd, uint timeout); 00126 #endif 00127 00128 CHARSET_INFO *default_client_charset_info = &my_charset_latin1; 00129 00130 00131 /**************************************************************************** 00132 A modified version of connect(). my_connect() allows you to specify 00133 a timeout value, in seconds, that we should wait until we 00134 derermine we can't connect to a particular host. If timeout is 0, 00135 my_connect() will behave exactly like connect(). 00136 00137 Base version coded by Steve Bernacki, Jr. <steve@navinet.net> 00138 *****************************************************************************/ 00139 00140 int my_connect(my_socket fd, const struct sockaddr *name, uint namelen, 00141 uint timeout) 00142 { 00143 #if defined(__WIN__) || defined(__NETWARE__) 00144 return connect(fd, (struct sockaddr*) name, namelen); 00145 #else 00146 int flags, res, s_err; 00147 00148 /* 00149 If they passed us a timeout of zero, we should behave 00150 exactly like the normal connect() call does. 00151 */ 00152 00153 if (timeout == 0) 00154 return connect(fd, (struct sockaddr*) name, namelen); 00155 00156 flags = fcntl(fd, F_GETFL, 0); /* Set socket to not block */ 00157 #ifdef O_NONBLOCK 00158 fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */ 00159 #endif 00160 00161 res= connect(fd, (struct sockaddr*) name, namelen); 00162 s_err= errno; /* Save the error... */ 00163 fcntl(fd, F_SETFL, flags); 00164 if ((res != 0) && (s_err != EINPROGRESS)) 00165 { 00166 errno= s_err; /* Restore it */ 00167 return(-1); 00168 } 00169 if (res == 0) /* Connected quickly! */ 00170 return(0); 00171 return wait_for_data(fd, timeout); 00172 #endif 00173 } 00174 00175 00176 /* 00177 Wait up to timeout seconds for a connection to be established. 00178 00179 We prefer to do this with poll() as there is no limitations with this. 00180 If not, we will use select() 00181 */ 00182 00183 #if !(defined(__WIN__) || defined(__NETWARE__)) 00184 00185 static int wait_for_data(my_socket fd, uint timeout) 00186 { 00187 #ifdef HAVE_POLL 00188 struct pollfd ufds; 00189 int res; 00190 00191 ufds.fd= fd; 00192 ufds.events= POLLIN | POLLPRI; 00193 if (!(res= poll(&ufds, 1, (int) timeout*1000))) 00194 { 00195 errno= EINTR; 00196 return -1; 00197 } 00198 if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI))) 00199 return -1; 00200 return 0; 00201 #else 00202 SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint); 00203 fd_set sfds; 00204 struct timeval tv; 00205 time_t start_time, now_time; 00206 int res, s_err; 00207 00208 if (fd >= FD_SETSIZE) /* Check if wrong error */ 00209 return 0; /* Can't use timeout */ 00210 00211 /* 00212 Our connection is "in progress." We can use the select() call to wait 00213 up to a specified period of time for the connection to suceed. 00214 If select() returns 0 (after waiting howevermany seconds), our socket 00215 never became writable (host is probably unreachable.) Otherwise, if 00216 select() returns 1, then one of two conditions exist: 00217 00218 1. An error occured. We use getsockopt() to check for this. 00219 2. The connection was set up sucessfully: getsockopt() will 00220 return 0 as an error. 00221 00222 Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk> 00223 who posted this method of timing out a connect() in 00224 comp.unix.programmer on August 15th, 1997. 00225 */ 00226 00227 FD_ZERO(&sfds); 00228 FD_SET(fd, &sfds); 00229 /* 00230 select could be interrupted by a signal, and if it is, 00231 the timeout should be adjusted and the select restarted 00232 to work around OSes that don't restart select and 00233 implementations of select that don't adjust tv upon 00234 failure to reflect the time remaining 00235 */ 00236 start_time = time(NULL); 00237 for (;;) 00238 { 00239 tv.tv_sec = (long) timeout; 00240 tv.tv_usec = 0; 00241 #if defined(HPUX10) && defined(THREAD) 00242 if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0) 00243 break; 00244 #else 00245 if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0) 00246 break; 00247 #endif 00248 if (res == 0) /* timeout */ 00249 return -1; 00250 now_time=time(NULL); 00251 timeout-= (uint) (now_time - start_time); 00252 if (errno != EINTR || (int) timeout <= 0) 00253 return -1; 00254 } 00255 00256 /* 00257 select() returned something more interesting than zero, let's 00258 see if we have any errors. If the next two statements pass, 00259 we've got an open socket! 00260 */ 00261 00262 s_err=0; 00263 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) 00264 return(-1); 00265 00266 if (s_err) 00267 { /* getsockopt could succeed */ 00268 errno = s_err; 00269 return(-1); /* but return an error... */ 00270 } 00271 return (0); /* ok */ 00272 #endif /* HAVE_POLL */ 00273 } 00274 #endif /* defined(__WIN__) || defined(__NETWARE__) */ 00275 00276 00277 /* 00278 Create a named pipe connection 00279 */ 00280 00281 #ifdef __WIN__ 00282 00283 HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, 00284 char **arg_unix_socket) 00285 { 00286 HANDLE hPipe=INVALID_HANDLE_VALUE; 00287 char pipe_name[1024]; 00288 DWORD dwMode; 00289 int i; 00290 my_bool testing_named_pipes=0; 00291 char *host= *arg_host, *unix_socket= *arg_unix_socket; 00292 00293 if ( ! unix_socket || (unix_socket)[0] == 0x00) 00294 unix_socket = mysql_unix_port; 00295 if (!host || !strcmp(host,LOCAL_HOST)) 00296 host=LOCAL_HOST_NAMEDPIPE; 00297 00298 00299 pipe_name[sizeof(pipe_name)-1]= 0; /* Safety if too long string */ 00300 strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\", host, "\\pipe\\", 00301 unix_socket, NullS); 00302 DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s", host, unix_socket)); 00303 00304 for (i=0 ; i < 100 ; i++) /* Don't retry forever */ 00305 { 00306 if ((hPipe = CreateFile(pipe_name, 00307 GENERIC_READ | GENERIC_WRITE, 00308 0, 00309 NULL, 00310 OPEN_EXISTING, 00311 0, 00312 NULL )) != INVALID_HANDLE_VALUE) 00313 break; 00314 if (GetLastError() != ERROR_PIPE_BUSY) 00315 { 00316 net->last_errno=CR_NAMEDPIPEOPEN_ERROR; 00317 strmov(net->sqlstate, unknown_sqlstate); 00318 my_snprintf(net->last_error, sizeof(net->last_error)-1, 00319 ER(net->last_errno), host, unix_socket, 00320 (ulong) GetLastError()); 00321 return INVALID_HANDLE_VALUE; 00322 } 00323 /* wait for for an other instance */ 00324 if (! WaitNamedPipe(pipe_name, connect_timeout*1000) ) 00325 { 00326 net->last_errno=CR_NAMEDPIPEWAIT_ERROR; 00327 strmov(net->sqlstate, unknown_sqlstate); 00328 my_snprintf(net->last_error, sizeof(net->last_error)-1, 00329 ER(net->last_errno), host, unix_socket, 00330 (ulong) GetLastError()); 00331 return INVALID_HANDLE_VALUE; 00332 } 00333 } 00334 if (hPipe == INVALID_HANDLE_VALUE) 00335 { 00336 net->last_errno=CR_NAMEDPIPEOPEN_ERROR; 00337 strmov(net->sqlstate, unknown_sqlstate); 00338 my_snprintf(net->last_error, sizeof(net->last_error)-1, 00339 ER(net->last_errno), host, unix_socket, 00340 (ulong) GetLastError()); 00341 return INVALID_HANDLE_VALUE; 00342 } 00343 dwMode = PIPE_READMODE_BYTE | PIPE_WAIT; 00344 if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) ) 00345 { 00346 CloseHandle( hPipe ); 00347 net->last_errno=CR_NAMEDPIPESETSTATE_ERROR; 00348 strmov(net->sqlstate, unknown_sqlstate); 00349 my_snprintf(net->last_error, sizeof(net->last_error)-1, 00350 ER(net->last_errno),host, unix_socket, 00351 (ulong) GetLastError()); 00352 return INVALID_HANDLE_VALUE; 00353 } 00354 *arg_host=host ; *arg_unix_socket=unix_socket; /* connect arg */ 00355 return (hPipe); 00356 } 00357 #endif 00358 00359 00360 /* 00361 Create new shared memory connection, return handler of connection 00362 00363 SYNOPSIS 00364 create_shared_memory() 00365 mysql Pointer of mysql structure 00366 net Pointer of net structure 00367 connect_timeout Timeout of connection 00368 */ 00369 00370 #ifdef HAVE_SMEM 00371 HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) 00372 { 00373 ulong smem_buffer_length = shared_memory_buffer_length + 4; 00374 /* 00375 event_connect_request is event object for start connection actions 00376 event_connect_answer is event object for confirm, that server put data 00377 handle_connect_file_map is file-mapping object, use for create shared 00378 memory 00379 handle_connect_map is pointer on shared memory 00380 handle_map is pointer on shared memory for client 00381 event_server_wrote, 00382 event_server_read, 00383 event_client_wrote, 00384 event_client_read are events for transfer data between server and client 00385 handle_file_map is file-mapping object, use for create shared memory 00386 */ 00387 HANDLE event_connect_request = NULL; 00388 HANDLE event_connect_answer = NULL; 00389 HANDLE handle_connect_file_map = NULL; 00390 char *handle_connect_map = NULL; 00391 00392 char *handle_map = NULL; 00393 HANDLE event_server_wrote = NULL; 00394 HANDLE event_server_read = NULL; 00395 HANDLE event_client_wrote = NULL; 00396 HANDLE event_client_read = NULL; 00397 HANDLE event_conn_closed = NULL; 00398 HANDLE handle_file_map = NULL; 00399 ulong connect_number; 00400 char connect_number_char[22], *p; 00401 char tmp[64]; 00402 char *suffix_pos; 00403 DWORD error_allow = 0; 00404 DWORD error_code = 0; 00405 DWORD event_access_rights= SYNCHRONIZE | EVENT_MODIFY_STATE; 00406 char *shared_memory_base_name = mysql->options.shared_memory_base_name; 00407 00408 /* 00409 The name of event and file-mapping events create agree next rule: 00410 shared_memory_base_name+unique_part 00411 Where: 00412 shared_memory_base_name is unique value for each server 00413 unique_part is uniquel value for each object (events and file-mapping) 00414 */ 00415 suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS); 00416 strmov(suffix_pos, "CONNECT_REQUEST"); 00417 if (!(event_connect_request= OpenEvent(event_access_rights, FALSE, tmp))) 00418 { 00419 error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR; 00420 goto err; 00421 } 00422 strmov(suffix_pos, "CONNECT_ANSWER"); 00423 if (!(event_connect_answer= OpenEvent(event_access_rights,FALSE,tmp))) 00424 { 00425 error_allow = CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR; 00426 goto err; 00427 } 00428 strmov(suffix_pos, "CONNECT_DATA"); 00429 if (!(handle_connect_file_map= OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp))) 00430 { 00431 error_allow = CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR; 00432 goto err; 00433 } 00434 if (!(handle_connect_map= MapViewOfFile(handle_connect_file_map, 00435 FILE_MAP_WRITE,0,0,sizeof(DWORD)))) 00436 { 00437 error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR; 00438 goto err; 00439 } 00440 00441 /* Send to server request of connection */ 00442 if (!SetEvent(event_connect_request)) 00443 { 00444 error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR; 00445 goto err; 00446 } 00447 00448 /* Wait of answer from server */ 00449 if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) != 00450 WAIT_OBJECT_0) 00451 { 00452 error_allow = CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR; 00453 goto err; 00454 } 00455 00456 /* Get number of connection */ 00457 connect_number = uint4korr(handle_connect_map);/*WAX2*/ 00458 p= int10_to_str(connect_number, connect_number_char, 10); 00459 00460 /* 00461 The name of event and file-mapping events create agree next rule: 00462 shared_memory_base_name+unique_part+number_of_connection 00463 00464 Where: 00465 shared_memory_base_name is uniquel value for each server 00466 unique_part is uniquel value for each object (events and file-mapping) 00467 number_of_connection is number of connection between server and client 00468 */ 00469 suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char, 00470 "_",NullS); 00471 strmov(suffix_pos, "DATA"); 00472 if ((handle_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL) 00473 { 00474 error_allow = CR_SHARED_MEMORY_FILE_MAP_ERROR; 00475 goto err2; 00476 } 00477 if ((handle_map = MapViewOfFile(handle_file_map,FILE_MAP_WRITE,0,0, 00478 smem_buffer_length)) == NULL) 00479 { 00480 error_allow = CR_SHARED_MEMORY_MAP_ERROR; 00481 goto err2; 00482 } 00483 00484 strmov(suffix_pos, "SERVER_WROTE"); 00485 if ((event_server_wrote = OpenEvent(event_access_rights,FALSE,tmp)) == NULL) 00486 { 00487 error_allow = CR_SHARED_MEMORY_EVENT_ERROR; 00488 goto err2; 00489 } 00490 00491 strmov(suffix_pos, "SERVER_READ"); 00492 if ((event_server_read = OpenEvent(event_access_rights,FALSE,tmp)) == NULL) 00493 { 00494 error_allow = CR_SHARED_MEMORY_EVENT_ERROR; 00495 goto err2; 00496 } 00497 00498 strmov(suffix_pos, "CLIENT_WROTE"); 00499 if ((event_client_wrote = OpenEvent(event_access_rights,FALSE,tmp)) == NULL) 00500 { 00501 error_allow = CR_SHARED_MEMORY_EVENT_ERROR; 00502 goto err2; 00503 } 00504 00505 strmov(suffix_pos, "CLIENT_READ"); 00506 if ((event_client_read = OpenEvent(event_access_rights,FALSE,tmp)) == NULL) 00507 { 00508 error_allow = CR_SHARED_MEMORY_EVENT_ERROR; 00509 goto err2; 00510 } 00511 00512 strmov(suffix_pos, "CONNECTION_CLOSED"); 00513 if ((event_conn_closed = OpenEvent(event_access_rights,FALSE,tmp)) == NULL) 00514 { 00515 error_allow = CR_SHARED_MEMORY_EVENT_ERROR; 00516 goto err2; 00517 } 00518 /* 00519 Set event that server should send data 00520 */ 00521 SetEvent(event_server_read); 00522 00523 err2: 00524 if (error_allow == 0) 00525 { 00526 net->vio= vio_new_win32shared_memory(net,handle_file_map,handle_map, 00527 event_server_wrote, 00528 event_server_read,event_client_wrote, 00529 event_client_read,event_conn_closed); 00530 } 00531 else 00532 { 00533 error_code = GetLastError(); 00534 if (event_server_read) 00535 CloseHandle(event_server_read); 00536 if (event_server_wrote) 00537 CloseHandle(event_server_wrote); 00538 if (event_client_read) 00539 CloseHandle(event_client_read); 00540 if (event_client_wrote) 00541 CloseHandle(event_client_wrote); 00542 if (event_conn_closed) 00543 CloseHandle(event_conn_closed); 00544 if (handle_map) 00545 UnmapViewOfFile(handle_map); 00546 if (handle_file_map) 00547 CloseHandle(handle_file_map); 00548 } 00549 err: 00550 if (error_allow) 00551 error_code = GetLastError(); 00552 if (event_connect_request) 00553 CloseHandle(event_connect_request); 00554 if (event_connect_answer) 00555 CloseHandle(event_connect_answer); 00556 if (handle_connect_map) 00557 UnmapViewOfFile(handle_connect_map); 00558 if (handle_connect_file_map) 00559 CloseHandle(handle_connect_file_map); 00560 if (error_allow) 00561 { 00562 net->last_errno=error_allow; 00563 strmov(net->sqlstate, unknown_sqlstate); 00564 if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR) 00565 my_snprintf(net->last_error,sizeof(net->last_error)-1, 00566 ER(net->last_errno),suffix_pos,error_code); 00567 else 00568 my_snprintf(net->last_error,sizeof(net->last_error)-1, 00569 ER(net->last_errno),error_code); 00570 return(INVALID_HANDLE_VALUE); 00571 } 00572 return(handle_map); 00573 } 00574 #endif 00575 00576 /***************************************************************************** 00577 Read a packet from server. Give error message if socket was down 00578 or packet is an error message 00579 *****************************************************************************/ 00580 00581 ulong 00582 cli_safe_read(MYSQL *mysql) 00583 { 00584 NET *net= &mysql->net; 00585 ulong len=0; 00586 init_sigpipe_variables 00587 00588 /* Don't give sigpipe errors if the client doesn't want them */ 00589 set_sigpipe(mysql); 00590 if (net->vio != 0) 00591 len=my_net_read(net); 00592 reset_sigpipe(mysql); 00593 00594 if (len == packet_error || len == 0) 00595 { 00596 DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", 00597 vio_description(net->vio),len)); 00598 #ifdef MYSQL_SERVER 00599 if (net->vio && vio_was_interrupted(net->vio)) 00600 return (packet_error); 00601 #endif /*MYSQL_SERVER*/ 00602 end_server(mysql); 00603 set_mysql_error(mysql, net->last_errno == ER_NET_PACKET_TOO_LARGE ? 00604 CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate); 00605 return (packet_error); 00606 } 00607 if (net->read_pos[0] == 255) 00608 { 00609 if (len > 3) 00610 { 00611 char *pos=(char*) net->read_pos+1; 00612 net->last_errno=uint2korr(pos); 00613 pos+=2; 00614 len-=2; 00615 if (protocol_41(mysql) && pos[0] == '#') 00616 { 00617 strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH); 00618 pos+= SQLSTATE_LENGTH+1; 00619 } 00620 (void) strmake(net->last_error,(char*) pos, 00621 min((uint) len,(uint) sizeof(net->last_error)-1)); 00622 } 00623 else 00624 set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate); 00625 /* 00626 Cover a protocol design error: error packet does not 00627 contain the server status. Therefore, the client has no way 00628 to find out whether there are more result sets of 00629 a multiple-result-set statement pending. Luckily, in 5.0 an 00630 error always aborts execution of a statement, wherever it is 00631 a multi-statement or a stored procedure, so it should be 00632 safe to unconditionally turn off the flag here. 00633 */ 00634 mysql->server_status&= ~SERVER_MORE_RESULTS_EXISTS; 00635 00636 DBUG_PRINT("error",("Got error: %d/%s (%s)", 00637 net->last_errno, net->sqlstate, net->last_error)); 00638 return(packet_error); 00639 } 00640 return len; 00641 } 00642 00643 void free_rows(MYSQL_DATA *cur) 00644 { 00645 if (cur) 00646 { 00647 free_root(&cur->alloc,MYF(0)); 00648 my_free((gptr) cur,MYF(0)); 00649 } 00650 } 00651 00652 my_bool 00653 cli_advanced_command(MYSQL *mysql, enum enum_server_command command, 00654 const char *header, ulong header_length, 00655 const char *arg, ulong arg_length, my_bool skip_check, 00656 MYSQL_STMT *stmt __attribute__((unused))) 00657 { 00658 NET *net= &mysql->net; 00659 my_bool result= 1; 00660 init_sigpipe_variables 00661 DBUG_ENTER("cli_advanced_command"); 00662 00663 /* Don't give sigpipe errors if the client doesn't want them */ 00664 set_sigpipe(mysql); 00665 00666 if (mysql->net.vio == 0) 00667 { /* Do reconnect if possible */ 00668 if (mysql_reconnect(mysql)) 00669 DBUG_RETURN(1); 00670 } 00671 if (mysql->status != MYSQL_STATUS_READY || 00672 mysql->server_status & SERVER_MORE_RESULTS_EXISTS) 00673 { 00674 DBUG_PRINT("error",("state: %d", mysql->status)); 00675 set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); 00676 DBUG_RETURN(1); 00677 } 00678 00679 net->last_error[0]=0; 00680 net->last_errno= 0; 00681 strmov(net->sqlstate, not_error_sqlstate); 00682 mysql->net.report_error=0; 00683 mysql->info=0; 00684 mysql->affected_rows= ~(my_ulonglong) 0; 00685 net_clear(&mysql->net); /* Clear receive buffer */ 00686 00687 if (net_write_command(net,(uchar) command, header, header_length, 00688 arg, arg_length)) 00689 { 00690 DBUG_PRINT("error",("Can't send command to server. Error: %d", 00691 socket_errno)); 00692 if (net->last_errno == ER_NET_PACKET_TOO_LARGE) 00693 { 00694 net->last_errno=CR_NET_PACKET_TOO_LARGE; 00695 strmov(net->last_error,ER(net->last_errno)); 00696 goto end; 00697 } 00698 end_server(mysql); 00699 if (mysql_reconnect(mysql)) 00700 goto end; 00701 if (net_write_command(net,(uchar) command, header, header_length, 00702 arg, arg_length)) 00703 { 00704 net->last_errno=CR_SERVER_GONE_ERROR; 00705 strmov(net->last_error,ER(net->last_errno)); 00706 goto end; 00707 } 00708 } 00709 result=0; 00710 if (!skip_check) 00711 result= ((mysql->packet_length=cli_safe_read(mysql)) == packet_error ? 00712 1 : 0); 00713 end: 00714 reset_sigpipe(mysql); 00715 DBUG_PRINT("exit",("result: %d", result)); 00716 DBUG_RETURN(result); 00717 } 00718 00719 void free_old_query(MYSQL *mysql) 00720 { 00721 DBUG_ENTER("free_old_query"); 00722 if (mysql->fields) 00723 free_root(&mysql->field_alloc,MYF(0)); 00724 init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */ 00725 mysql->fields= 0; 00726 mysql->field_count= 0; /* For API */ 00727 mysql->warning_count= 0; 00728 mysql->info= 0; 00729 DBUG_VOID_RETURN; 00730 } 00731 00732 /* 00733 Set the internal error message to mysql handler 00734 */ 00735 00736 void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate) 00737 { 00738 NET *net; 00739 DBUG_ENTER("set_mysql_error"); 00740 DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode))); 00741 DBUG_ASSERT(mysql != 0); 00742 00743 net= &mysql->net; 00744 net->last_errno= errcode; 00745 strmov(net->last_error, ER(errcode)); 00746 strmov(net->sqlstate, sqlstate); 00747 00748 DBUG_VOID_RETURN; 00749 } 00750 00751 /* 00752 Flush result set sent from server 00753 */ 00754 00755 static void cli_flush_use_result(MYSQL *mysql) 00756 { 00757 /* Clear the current execution status */ 00758 DBUG_ENTER("cli_flush_use_result"); 00759 DBUG_PRINT("warning",("Not all packets read, clearing them")); 00760 for (;;) 00761 { 00762 ulong pkt_len; 00763 if ((pkt_len=cli_safe_read(mysql)) == packet_error) 00764 break; 00765 if (pkt_len <= 8 && mysql->net.read_pos[0] == 254) 00766 { 00767 if (protocol_41(mysql)) 00768 { 00769 char *pos= (char*) mysql->net.read_pos + 1; 00770 mysql->warning_count=uint2korr(pos); pos+=2; 00771 mysql->server_status=uint2korr(pos); pos+=2; 00772 } 00773 break; /* End of data */ 00774 } 00775 } 00776 DBUG_VOID_RETURN; 00777 } 00778 00779 00780 #ifdef __WIN__ 00781 static my_bool is_NT(void) 00782 { 00783 char *os=getenv("OS"); 00784 return (os && !strcmp(os, "Windows_NT")) ? 1 : 0; 00785 } 00786 #endif 00787 00788 00789 #ifdef CHECK_LICENSE 00790 /* 00791 Check server side variable 'license'. 00792 If the variable does not exist or does not contain 'Commercial', 00793 we're talking to non-commercial server from commercial client. 00794 SYNOPSIS 00795 check_license() 00796 RETURN VALUE 00797 0 success 00798 !0 network error or the server is not commercial. 00799 Error code is saved in mysql->net.last_errno. 00800 */ 00801 00802 static int check_license(MYSQL *mysql) 00803 { 00804 MYSQL_ROW row; 00805 MYSQL_RES *res; 00806 NET *net= &mysql->net; 00807 static const char query[]= "SELECT @@license"; 00808 static const char required_license[]= STRINGIFY_ARG(LICENSE); 00809 00810 if (mysql_real_query(mysql, query, sizeof(query)-1)) 00811 { 00812 if (net->last_errno == ER_UNKNOWN_SYSTEM_VARIABLE) 00813 { 00814 net->last_errno= CR_WRONG_LICENSE; 00815 my_snprintf(net->last_error, sizeof(net->last_error)-1, 00816 ER(net->last_errno), required_license); 00817 } 00818 return 1; 00819 } 00820 if (!(res= mysql_use_result(mysql))) 00821 return 1; 00822 row= mysql_fetch_row(res); 00823 /* 00824 If no rows in result set, or column value is NULL (none of these 00825 two is ever true for server variables now), or column value 00826 mismatch, set wrong license error. 00827 */ 00828 if (!net->last_errno && 00829 (!row || !row[0] || 00830 strncmp(row[0], required_license, sizeof(required_license)))) 00831 { 00832 net->last_errno= CR_WRONG_LICENSE; 00833 my_snprintf(net->last_error, sizeof(net->last_error)-1, 00834 ER(net->last_errno), required_license); 00835 } 00836 mysql_free_result(res); 00837 return net->last_errno; 00838 } 00839 #endif /* CHECK_LICENSE */ 00840 00841 00842 /************************************************************************** 00843 Shut down connection 00844 **************************************************************************/ 00845 00846 void end_server(MYSQL *mysql) 00847 { 00848 DBUG_ENTER("end_server"); 00849 if (mysql->net.vio != 0) 00850 { 00851 init_sigpipe_variables 00852 DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio))); 00853 set_sigpipe(mysql); 00854 vio_delete(mysql->net.vio); 00855 reset_sigpipe(mysql); 00856 mysql->net.vio= 0; /* Marker */ 00857 } 00858 net_end(&mysql->net); 00859 free_old_query(mysql); 00860 DBUG_VOID_RETURN; 00861 } 00862 00863 00864 void STDCALL 00865 mysql_free_result(MYSQL_RES *result) 00866 { 00867 DBUG_ENTER("mysql_free_result"); 00868 DBUG_PRINT("enter",("mysql_res: %lx",result)); 00869 if (result) 00870 { 00871 MYSQL *mysql= result->handle; 00872 if (mysql) 00873 { 00874 if (mysql->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled) 00875 mysql->unbuffered_fetch_owner= 0; 00876 if (mysql->status == MYSQL_STATUS_USE_RESULT) 00877 { 00878 (*mysql->methods->flush_use_result)(mysql); 00879 mysql->status=MYSQL_STATUS_READY; 00880 if (mysql->unbuffered_fetch_owner) 00881 *mysql->unbuffered_fetch_owner= TRUE; 00882 } 00883 } 00884 free_rows(result->data); 00885 if (result->fields) 00886 free_root(&result->field_alloc,MYF(0)); 00887 if (result->row) 00888 my_free((gptr) result->row,MYF(0)); 00889 my_free((gptr) result,MYF(0)); 00890 } 00891 DBUG_VOID_RETURN; 00892 } 00893 00894 /**************************************************************************** 00895 Get options from my.cnf 00896 ****************************************************************************/ 00897 00898 static const char *default_options[]= 00899 { 00900 "port","socket","compress","password","pipe", "timeout", "user", 00901 "init-command", "host", "database", "debug", "return-found-rows", 00902 "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", 00903 "character-sets-dir", "default-character-set", "interactive-timeout", 00904 "connect-timeout", "local-infile", "disable-local-infile", 00905 "replication-probe", "enable-reads-from-master", "repl-parse-query", 00906 "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name", 00907 "multi-results", "multi-statements", "multi-queries", "secure-auth", 00908 "report-data-truncation", 00909 NullS 00910 }; 00911 00912 static TYPELIB option_types={array_elements(default_options)-1, 00913 "options",default_options, NULL}; 00914 00915 const char *sql_protocol_names_lib[] = 00916 { "TCP", "SOCKET", "PIPE", "MEMORY", NullS }; 00917 TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"", 00918 sql_protocol_names_lib, NULL}; 00919 00920 static int add_init_command(struct st_mysql_options *options, const char *cmd) 00921 { 00922 char *tmp; 00923 00924 if (!options->init_commands) 00925 { 00926 options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY), 00927 MYF(MY_WME)); 00928 init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO); 00929 } 00930 00931 if (!(tmp= my_strdup(cmd,MYF(MY_WME))) || 00932 insert_dynamic(options->init_commands, (gptr)&tmp)) 00933 { 00934 my_free(tmp, MYF(MY_ALLOW_ZERO_PTR)); 00935 return 1; 00936 } 00937 00938 return 0; 00939 } 00940 00941 void mysql_read_default_options(struct st_mysql_options *options, 00942 const char *filename,const char *group) 00943 { 00944 int argc; 00945 char *argv_buff[1],**argv; 00946 const char *groups[3]; 00947 DBUG_ENTER("mysql_read_default_options"); 00948 DBUG_PRINT("enter",("file: %s group: %s",filename,group ? group :"NULL")); 00949 00950 argc=1; argv=argv_buff; argv_buff[0]= (char*) "client"; 00951 groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0; 00952 00953 load_defaults(filename, groups, &argc, &argv); 00954 if (argc != 1) /* If some default option */ 00955 { 00956 char **option=argv; 00957 while (*++option) 00958 { 00959 /* DBUG_PRINT("info",("option: %s",option[0])); */ 00960 if (option[0][0] == '-' && option[0][1] == '-') 00961 { 00962 char *end=strcend(*option,'='); 00963 char *opt_arg=0; 00964 if (*end) 00965 { 00966 opt_arg=end+1; 00967 *end=0; /* Remove '=' */ 00968 } 00969 /* Change all '_' in variable name to '-' */ 00970 for (end= *option ; *(end= strcend(end,'_')) ; ) 00971 *end= '-'; 00972 switch (find_type(*option+2,&option_types,2)) { 00973 case 1: /* port */ 00974 if (opt_arg) 00975 options->port=atoi(opt_arg); 00976 break; 00977 case 2: /* socket */ 00978 if (opt_arg) 00979 { 00980 my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR)); 00981 options->unix_socket=my_strdup(opt_arg,MYF(MY_WME)); 00982 } 00983 break; 00984 case 3: /* compress */ 00985 options->compress=1; 00986 options->client_flag|= CLIENT_COMPRESS; 00987 break; 00988 case 4: /* password */ 00989 if (opt_arg) 00990 { 00991 my_free(options->password,MYF(MY_ALLOW_ZERO_PTR)); 00992 options->password=my_strdup(opt_arg,MYF(MY_WME)); 00993 } 00994 break; 00995 case 5: 00996 options->protocol = MYSQL_PROTOCOL_PIPE; 00997 case 20: /* connect_timeout */ 00998 case 6: /* timeout */ 00999 if (opt_arg) 01000 options->connect_timeout=atoi(opt_arg); 01001 break; 01002 case 7: /* user */ 01003 if (opt_arg) 01004 { 01005 my_free(options->user,MYF(MY_ALLOW_ZERO_PTR)); 01006 options->user=my_strdup(opt_arg,MYF(MY_WME)); 01007 } 01008 break; 01009 case 8: /* init-command */ 01010 add_init_command(options,opt_arg); 01011 break; 01012 case 9: /* host */ 01013 if (opt_arg) 01014 { 01015 my_free(options->host,MYF(MY_ALLOW_ZERO_PTR)); 01016 options->host=my_strdup(opt_arg,MYF(MY_WME)); 01017 } 01018 break; 01019 case 10: /* database */ 01020 if (opt_arg) 01021 { 01022 my_free(options->db,MYF(MY_ALLOW_ZERO_PTR)); 01023 options->db=my_strdup(opt_arg,MYF(MY_WME)); 01024 } 01025 break; 01026 case 11: /* debug */ 01027 #ifdef MYSQL_CLIENT 01028 mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace"); 01029 break; 01030 #endif 01031 case 12: /* return-found-rows */ 01032 options->client_flag|=CLIENT_FOUND_ROWS; 01033 break; 01034 #ifdef HAVE_OPENSSL 01035 case 13: /* ssl_key */ 01036 my_free(options->ssl_key, MYF(MY_ALLOW_ZERO_PTR)); 01037 options->ssl_key = my_strdup(opt_arg, MYF(MY_WME)); 01038 break; 01039 case 14: /* ssl_cert */ 01040 my_free(options->ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); 01041 options->ssl_cert = my_strdup(opt_arg, MYF(MY_WME)); 01042 break; 01043 case 15: /* ssl_ca */ 01044 my_free(options->ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); 01045 options->ssl_ca = my_strdup(opt_arg, MYF(MY_WME)); 01046 break; 01047 case 16: /* ssl_capath */ 01048 my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); 01049 options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME)); 01050 break; 01051 #else 01052 case 13: /* Ignore SSL options */ 01053 case 14: 01054 case 15: 01055 case 16: 01056 break; 01057 #endif /* HAVE_OPENSSL */ 01058 case 17: /* charset-lib */ 01059 my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR)); 01060 options->charset_dir = my_strdup(opt_arg, MYF(MY_WME)); 01061 break; 01062 case 18: 01063 my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR)); 01064 options->charset_name = my_strdup(opt_arg, MYF(MY_WME)); 01065 break; 01066 case 19: /* Interactive-timeout */ 01067 options->client_flag|= CLIENT_INTERACTIVE; 01068 break; 01069 case 21: 01070 if (!opt_arg || atoi(opt_arg) != 0) 01071 options->client_flag|= CLIENT_LOCAL_FILES; 01072 else 01073 options->client_flag&= ~CLIENT_LOCAL_FILES; 01074 break; 01075 case 22: 01076 options->client_flag&= ~CLIENT_LOCAL_FILES; 01077 break; 01078 case 23: /* replication probe */ 01079 #ifndef TO_BE_DELETED 01080 options->rpl_probe= 1; 01081 #endif 01082 break; 01083 case 24: /* enable-reads-from-master */ 01084 options->no_master_reads= 0; 01085 break; 01086 case 25: /* repl-parse-query */ 01087 #ifndef TO_BE_DELETED 01088 options->rpl_parse= 1; 01089 #endif 01090 break; 01091 case 27: 01092 if (opt_arg) 01093 options->max_allowed_packet= atoi(opt_arg); 01094 break; 01095 case 28: /* protocol */ 01096 if ((options->protocol= find_type(opt_arg, 01097 &sql_protocol_typelib,0)) <= 0) 01098 { 01099 fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg); 01100 exit(1); 01101 } 01102 break; 01103 case 29: /* shared_memory_base_name */ 01104 #ifdef HAVE_SMEM 01105 if (options->shared_memory_base_name != def_shared_memory_base_name) 01106 my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); 01107 options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME)); 01108 #endif 01109 break; 01110 case 30: 01111 options->client_flag|= CLIENT_MULTI_RESULTS; 01112 break; 01113 case 31: 01114 case 32: 01115 options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS; 01116 break; 01117 case 33: /* secure-auth */ 01118 options->secure_auth= TRUE; 01119 break; 01120 case 34: /* report-data-truncation */ 01121 options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1; 01122 break; 01123 default: 01124 DBUG_PRINT("warning",("unknown option: %s",option[0])); 01125 } 01126 } 01127 } 01128 } 01129 free_defaults(argv); 01130 DBUG_VOID_RETURN; 01131 } 01132 01133 01134 /************************************************************************** 01135 Get column lengths of the current row 01136 If one uses mysql_use_result, res->lengths contains the length information, 01137 else the lengths are calculated from the offset between pointers. 01138 **************************************************************************/ 01139 01140 static void cli_fetch_lengths(ulong *to, MYSQL_ROW column, 01141 unsigned int field_count) 01142 { 01143 ulong *prev_length; 01144 byte *start=0; 01145 MYSQL_ROW end; 01146 01147 prev_length=0; /* Keep gcc happy */ 01148 for (end=column + field_count + 1 ; column != end ; column++, to++) 01149 { 01150 if (!*column) 01151 { 01152 *to= 0; /* Null */ 01153 continue; 01154 } 01155 if (start) /* Found end of prev string */ 01156 *prev_length= (ulong) (*column-start-1); 01157 start= *column; 01158 prev_length= to; 01159 } 01160 } 01161 01162 /*************************************************************************** 01163 Change field rows to field structs 01164 ***************************************************************************/ 01165 01166 MYSQL_FIELD * 01167 unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, 01168 my_bool default_value, uint server_capabilities) 01169 { 01170 MYSQL_ROWS *row; 01171 MYSQL_FIELD *field,*result; 01172 ulong lengths[9]; /* Max of fields */ 01173 DBUG_ENTER("unpack_fields"); 01174 01175 field= result= (MYSQL_FIELD*) alloc_root(alloc, 01176 (uint) sizeof(*field)*fields); 01177 if (!result) 01178 { 01179 free_rows(data); /* Free old data */ 01180 DBUG_RETURN(0); 01181 } 01182 bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields); 01183 if (server_capabilities & CLIENT_PROTOCOL_41) 01184 { 01185 /* server is 4.1, and returns the new field result format */ 01186 for (row=data->data; row ; row = row->next,field++) 01187 { 01188 uchar *pos; 01189 cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7); 01190 field->catalog = strdup_root(alloc,(char*) row->data[0]); 01191 field->db = strdup_root(alloc,(char*) row->data[1]); 01192 field->table = strdup_root(alloc,(char*) row->data[2]); 01193 field->org_table= strdup_root(alloc,(char*) row->data[3]); 01194 field->name = strdup_root(alloc,(char*) row->data[4]); 01195 field->org_name = strdup_root(alloc,(char*) row->data[5]); 01196 01197 field->catalog_length= lengths[0]; 01198 field->db_length= lengths[1]; 01199 field->table_length= lengths[2]; 01200 field->org_table_length= lengths[3]; 01201 field->name_length= lengths[4]; 01202 field->org_name_length= lengths[5]; 01203 01204 /* Unpack fixed length parts */ 01205 pos= (uchar*) row->data[6]; 01206 field->charsetnr= uint2korr(pos); 01207 field->length= (uint) uint4korr(pos+2); 01208 field->type= (enum enum_field_types) pos[6]; 01209 field->flags= uint2korr(pos+7); 01210 field->decimals= (uint) pos[9]; 01211 01212 if (INTERNAL_NUM_FIELD(field)) 01213 field->flags|= NUM_FLAG; 01214 if (default_value && row->data[7]) 01215 { 01216 field->def=strdup_root(alloc,(char*) row->data[7]); 01217 field->def_length= lengths[7]; 01218 } 01219 else 01220 field->def=0; 01221 field->max_length= 0; 01222 } 01223 } 01224 #ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL 01225 else 01226 { 01227 /* old protocol, for backward compatibility */ 01228 for (row=data->data; row ; row = row->next,field++) 01229 { 01230 cli_fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5); 01231 field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]); 01232 field->name= strdup_root(alloc,(char*) row->data[1]); 01233 field->length= (uint) uint3korr(row->data[2]); 01234 field->type= (enum enum_field_types) (uchar) row->data[3][0]; 01235 01236 field->catalog=(char*) ""; 01237 field->db= (char*) ""; 01238 field->catalog_length= 0; 01239 field->db_length= 0; 01240 field->org_table_length= field->table_length= lengths[0]; 01241 field->name_length= lengths[1]; 01242 01243 if (server_capabilities & CLIENT_LONG_FLAG) 01244 { 01245 field->flags= uint2korr(row->data[4]); 01246 field->decimals=(uint) (uchar) row->data[4][2]; 01247 } 01248 else 01249 { 01250 field->flags= (uint) (uchar) row->data[4][0]; 01251 field->decimals=(uint) (uchar) row->data[4][1]; 01252 } 01253 if (INTERNAL_NUM_FIELD(field)) 01254 field->flags|= NUM_FLAG; 01255 if (default_value && row->data[5]) 01256 { 01257 field->def=strdup_root(alloc,(char*) row->data[5]); 01258 field->def_length= lengths[5]; 01259 } 01260 else 01261 field->def=0; 01262 field->max_length= 0; 01263 } 01264 } 01265 #endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */ 01266 free_rows(data); /* Free old data */ 01267 DBUG_RETURN(result); 01268 } 01269 01270 /* Read all rows (fields or data) from server */ 01271 01272 MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, 01273 unsigned int fields) 01274 { 01275 uint field; 01276 ulong pkt_len; 01277 ulong len; 01278 uchar *cp; 01279 char *to, *end_to; 01280 MYSQL_DATA *result; 01281 MYSQL_ROWS **prev_ptr,*cur; 01282 NET *net = &mysql->net; 01283 DBUG_ENTER("cli_read_rows"); 01284 01285 if ((pkt_len= cli_safe_read(mysql)) == packet_error) 01286 DBUG_RETURN(0); 01287 if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), 01288 MYF(MY_WME | MY_ZEROFILL)))) 01289 { 01290 set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); 01291 DBUG_RETURN(0); 01292 } 01293 init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */ 01294 result->alloc.min_malloc=sizeof(MYSQL_ROWS); 01295 prev_ptr= &result->data; 01296 result->rows=0; 01297 result->fields=fields; 01298 01299 /* 01300 The last EOF packet is either a single 254 character or (in MySQL 4.1) 01301 254 followed by 1-7 status bytes. 01302 01303 This doesn't conflict with normal usage of 254 which stands for a 01304 string where the length of the string is 8 bytes. (see net_field_length()) 01305 */ 01306 01307 while (*(cp=net->read_pos) != 254 || pkt_len >= 8) 01308 { 01309 result->rows++; 01310 if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc, 01311 sizeof(MYSQL_ROWS))) || 01312 !(cur->data= ((MYSQL_ROW) 01313 alloc_root(&result->alloc, 01314 (fields+1)*sizeof(char *)+pkt_len)))) 01315 { 01316 free_rows(result); 01317 set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); 01318 DBUG_RETURN(0); 01319 } 01320 *prev_ptr=cur; 01321 prev_ptr= &cur->next; 01322 to= (char*) (cur->data+fields+1); 01323 end_to=to+pkt_len-1; 01324 for (field=0 ; field < fields ; field++) 01325 { 01326 if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH) 01327 { /* null field */ 01328 cur->data[field] = 0; 01329 } 01330 else 01331 { 01332 cur->data[field] = to; 01333 if (len > (ulong) (end_to - to)) 01334 { 01335 free_rows(result); 01336 set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate); 01337 DBUG_RETURN(0); 01338 } 01339 memcpy(to,(char*) cp,len); to[len]=0; 01340 to+=len+1; 01341 cp+=len; 01342 if (mysql_fields) 01343 { 01344 if (mysql_fields[field].max_length < len) 01345 mysql_fields[field].max_length=len; 01346 } 01347 } 01348 } 01349 cur->data[field]=to; /* End of last field */ 01350 if ((pkt_len=cli_safe_read(mysql)) == packet_error) 01351 { 01352 free_rows(result); 01353 DBUG_RETURN(0); 01354 } 01355 } 01356 *prev_ptr=0; /* last pointer is null */ 01357 if (pkt_len > 1) /* MySQL 4.1 protocol */ 01358 { 01359 mysql->warning_count= uint2korr(cp+1); 01360 mysql->server_status= uint2korr(cp+3); 01361 DBUG_PRINT("info",("status: %u warning_count: %u", 01362 mysql->server_status, mysql->warning_count)); 01363 } 01364 DBUG_PRINT("exit",("Got %d rows",result->rows)); 01365 DBUG_RETURN(result); 01366 } 01367 01368 /* 01369 Read one row. Uses packet buffer as storage for fields. 01370 When next packet is read, the previous field values are destroyed 01371 */ 01372 01373 01374 static int 01375 read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) 01376 { 01377 uint field; 01378 ulong pkt_len,len; 01379 uchar *pos, *prev_pos, *end_pos; 01380 NET *net= &mysql->net; 01381 01382 if ((pkt_len=cli_safe_read(mysql)) == packet_error) 01383 return -1; 01384 if (pkt_len <= 8 && net->read_pos[0] == 254) 01385 { 01386 if (pkt_len > 1) /* MySQL 4.1 protocol */ 01387 { 01388 mysql->warning_count= uint2korr(net->read_pos+1); 01389 mysql->server_status= uint2korr(net->read_pos+3); 01390 } 01391 return 1; /* End of data */ 01392 } 01393 prev_pos= 0; /* allowed to write at packet[-1] */ 01394 pos=net->read_pos; 01395 end_pos=pos+pkt_len; 01396 for (field=0 ; field < fields ; field++) 01397 { 01398 if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH) 01399 { /* null field */ 01400 row[field] = 0; 01401 *lengths++=0; 01402 } 01403 else 01404 { 01405 if (len > (ulong) (end_pos - pos)) 01406 { 01407 set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate); 01408 return -1; 01409 } 01410 row[field] = (char*) pos; 01411 pos+=len; 01412 *lengths++=len; 01413 } 01414 if (prev_pos) 01415 *prev_pos=0; /* Terminate prev field */ 01416 prev_pos=pos; 01417 } 01418 row[field]=(char*) prev_pos+1; /* End of last field */ 01419 *prev_pos=0; /* Terminate last field */ 01420 return 0; 01421 } 01422 01423 01424 /**************************************************************************** 01425 Init MySQL structure or allocate one 01426 ****************************************************************************/ 01427 01428 MYSQL * STDCALL 01429 mysql_init(MYSQL *mysql) 01430 { 01431 if (mysql_server_init(0, NULL, NULL)) 01432 return 0; 01433 if (!mysql) 01434 { 01435 if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL)))) 01436 return 0; 01437 mysql->free_me=1; 01438 } 01439 else 01440 bzero((char*) (mysql), sizeof(*(mysql))); 01441 mysql->options.connect_timeout= CONNECT_TIMEOUT; 01442 mysql->last_used_con= mysql->next_slave= mysql->master = mysql; 01443 mysql->charset=default_client_charset_info; 01444 strmov(mysql->net.sqlstate, not_error_sqlstate); 01445 /* 01446 By default, we are a replication pivot. The caller must reset it 01447 after we return if this is not the case. 01448 */ 01449 #ifndef TO_BE_DELETED 01450 mysql->rpl_pivot = 1; 01451 #endif 01452 01453 /* 01454 Only enable LOAD DATA INFILE by default if configured with 01455 --enable-local-infile 01456 */ 01457 01458 #if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER) 01459 mysql->options.client_flag|= CLIENT_LOCAL_FILES; 01460 #endif 01461 01462 #ifdef HAVE_SMEM 01463 mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name; 01464 #endif 01465 01466 mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION; 01467 mysql->options.report_data_truncation= TRUE; /* default */ 01468 01469 /* 01470 By default we don't reconnect because it could silently corrupt data (after 01471 reconnection you potentially lose table locks, user variables, session 01472 variables (transactions but they are specifically dealt with in 01473 mysql_reconnect()). 01474 This is a change: < 5.0.3 mysql->reconnect was set to 1 by default. 01475 How this change impacts existing apps: 01476 - existing apps which relyed on the default will see a behaviour change; 01477 they will have to set reconnect=1 after mysql_real_connect(). 01478 - existing apps which explicitely asked for reconnection (the only way they 01479 could do it was by setting mysql.reconnect to 1 after mysql_real_connect()) 01480 will not see a behaviour change. 01481 - existing apps which explicitely asked for no reconnection 01482 (mysql.reconnect=0) will not see a behaviour change. 01483 */ 01484 mysql->reconnect= 0; 01485 01486 return mysql; 01487 } 01488 01489 01490 /* 01491 Fill in SSL part of MYSQL structure and set 'use_ssl' flag. 01492 NB! Errors are not reported until you do mysql_real_connect. 01493 */ 01494 01495 #define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME)) 01496 01497 my_bool STDCALL 01498 mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , 01499 const char *key __attribute__((unused)), 01500 const char *cert __attribute__((unused)), 01501 const char *ca __attribute__((unused)), 01502 const char *capath __attribute__((unused)), 01503 const char *cipher __attribute__((unused))) 01504 { 01505 DBUG_ENTER("mysql_ssl_set"); 01506 #ifdef HAVE_OPENSSL 01507 mysql->options.ssl_key= strdup_if_not_null(key); 01508 mysql->options.ssl_cert= strdup_if_not_null(cert); 01509 mysql->options.ssl_ca= strdup_if_not_null(ca); 01510 mysql->options.ssl_capath= strdup_if_not_null(capath); 01511 mysql->options.ssl_cipher= strdup_if_not_null(cipher); 01512 mysql->options.ssl_verify_server_cert= FALSE; /* Off by default */ 01513 #endif /* HAVE_OPENSSL */ 01514 DBUG_RETURN(0); 01515 } 01516 01517 01518 /* 01519 Free strings in the SSL structure and clear 'use_ssl' flag. 01520 NB! Errors are not reported until you do mysql_real_connect. 01521 */ 01522 01523 #ifdef HAVE_OPENSSL 01524 01525 static void 01526 mysql_ssl_free(MYSQL *mysql __attribute__((unused))) 01527 { 01528 struct st_VioSSLFd *ssl_fd= (struct st_VioSSLFd*) mysql->connector_fd; 01529 DBUG_ENTER("mysql_ssl_free"); 01530 01531 my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); 01532 my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); 01533 my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); 01534 my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); 01535 my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); 01536 if (ssl_fd) 01537 SSL_CTX_free(ssl_fd->ssl_context); 01538 my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); 01539 mysql->options.ssl_key = 0; 01540 mysql->options.ssl_cert = 0; 01541 mysql->options.ssl_ca = 0; 01542 mysql->options.ssl_capath = 0; 01543 mysql->options.ssl_cipher= 0; 01544 mysql->options.use_ssl = FALSE; 01545 mysql->connector_fd = 0; 01546 DBUG_VOID_RETURN; 01547 } 01548 01549 #endif /* HAVE_OPENSSL */ 01550 01551 /* 01552 Return the SSL cipher (if any) used for current 01553 connection to the server. 01554 01555 SYNOPSYS 01556 mysql_get_ssl_cipher() 01557 mysql pointer to the mysql connection 01558 01559 */ 01560 01561 const char * STDCALL 01562 mysql_get_ssl_cipher(MYSQL *mysql) 01563 { 01564 DBUG_ENTER("mysql_get_ssl_cipher"); 01565 #ifdef HAVE_OPENSSL 01566 if (mysql->net.vio && mysql->net.vio->ssl_arg) 01567 DBUG_RETURN(SSL_get_cipher_name((SSL*)mysql->net.vio->ssl_arg)); 01568 #endif /* HAVE_OPENSSL */ 01569 DBUG_RETURN(NULL); 01570 } 01571 01572 01573 /* 01574 Check the server's (subject) Common Name against the 01575 hostname we connected to 01576 01577 SYNOPSIS 01578 ssl_verify_server_cert() 01579 vio pointer to a SSL connected vio 01580 server_hostname name of the server that we connected to 01581 01582 RETURN VALUES 01583 0 Success 01584 1 Failed to validate server 01585 01586 */ 01587 01588 #ifdef HAVE_OPENSSL 01589 01590 static int ssl_verify_server_cert(Vio *vio, const char* server_hostname) 01591 { 01592 SSL *ssl; 01593 X509 *server_cert; 01594 char *cp1, *cp2; 01595 char buf[256]; 01596 DBUG_ENTER("ssl_verify_server_cert"); 01597 DBUG_PRINT("enter", ("server_hostname: %s", server_hostname)); 01598 01599 if (!(ssl= (SSL*)vio->ssl_arg)) 01600 { 01601 DBUG_PRINT("error", ("No SSL pointer found")); 01602 DBUG_RETURN(1); 01603 } 01604 01605 if (!server_hostname) 01606 { 01607 DBUG_PRINT("error", ("No server hostname supplied")); 01608 DBUG_RETURN(1); 01609 } 01610 01611 if (!(server_cert= SSL_get_peer_certificate(ssl))) 01612 { 01613 DBUG_PRINT("error", ("Could not get server certificate")); 01614 DBUG_RETURN(1); 01615 } 01616 01617 /* 01618 We already know that the certificate exchanged was valid; the SSL library 01619 handled that. Now we need to verify that the contents of the certificate 01620 are what we expect. 01621 */ 01622 01623 X509_NAME_oneline(X509_get_subject_name(server_cert), buf, sizeof(buf)); 01624 X509_free (server_cert); 01625 01626 DBUG_PRINT("info", ("hostname in cert: %s", buf)); 01627 cp1= strstr(buf, "/CN="); 01628 if (cp1) 01629 { 01630 cp1+= 4; /* Skip the "/CN=" that we found */ 01631 /* Search for next / which might be the delimiter for email */ 01632 cp2= strchr(cp1, '/'); 01633 if (cp2) 01634 *cp2= '\0'; 01635 DBUG_PRINT("info", ("Server hostname in cert: %s", cp1)); 01636 if (!strcmp(cp1, server_hostname)) 01637 { 01638 /* Success */ 01639 DBUG_RETURN(0); 01640 } 01641 } 01642 DBUG_PRINT("error", ("SSL certificate validation failure")); 01643 DBUG_RETURN(1); 01644 } 01645 01646 #endif /* HAVE_OPENSSL */ 01647 01648 01649 /* 01650 Note that the mysql argument must be initialized with mysql_init() 01651 before calling mysql_real_connect ! 01652 */ 01653 01654 static my_bool cli_read_query_result(MYSQL *mysql); 01655 static MYSQL_RES *cli_use_result(MYSQL *mysql); 01656 01657 static MYSQL_METHODS client_methods= 01658 { 01659 cli_read_query_result, /* read_query_result */ 01660 cli_advanced_command, /* advanced_command */ 01661 cli_read_rows, /* read_rows */ 01662 cli_use_result, /* use_result */ 01663 cli_fetch_lengths, /* fetch_lengths */ 01664 cli_flush_use_result /* flush_use_result */ 01665 #ifndef MYSQL_SERVER 01666 ,cli_list_fields, /* list_fields */ 01667 cli_read_prepare_result, /* read_prepare_result */ 01668 cli_stmt_execute, /* stmt_execute */ 01669 cli_read_binary_rows, /* read_binary_rows */ 01670 cli_unbuffered_fetch, /* unbuffered_fetch */ 01671 NULL, /* free_embedded_thd */ 01672 cli_read_statistics, /* read_statistics */ 01673 cli_read_query_result, /* next_result */ 01674 cli_read_change_user_result, /* read_change_user_result */ 01675 cli_read_binary_rows /* read_rows_from_cursor */ 01676 #endif 01677 }; 01678 01679 C_MODE_START 01680 int mysql_init_character_set(MYSQL *mysql) 01681 { 01682 NET *net= &mysql->net; 01683 const char *default_collation_name; 01684 01685 /* Set character set */ 01686 if (!mysql->options.charset_name) 01687 { 01688 default_collation_name= MYSQL_DEFAULT_COLLATION_NAME; 01689 if (!(mysql->options.charset_name= 01690 my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME)))) 01691 return 1; 01692 } 01693 else 01694 default_collation_name= NULL; 01695 01696 { 01697 const char *save= charsets_dir; 01698 if (mysql->options.charset_dir) 01699 charsets_dir=mysql->options.charset_dir; 01700 mysql->charset=get_charset_by_csname(mysql->options.charset_name, 01701 MY_CS_PRIMARY, MYF(MY_WME)); 01702 if (mysql->charset && default_collation_name) 01703 { 01704 CHARSET_INFO *collation; 01705 if ((collation= 01706 get_charset_by_name(default_collation_name, MYF(MY_WME)))) 01707 { 01708 if (!my_charset_same(mysql->charset, collation)) 01709 { 01710 my_printf_error(ER_UNKNOWN_ERROR, 01711 "COLLATION %s is not valid for CHARACTER SET %s", 01712 MYF(0), 01713 default_collation_name, mysql->options.charset_name); 01714 mysql->charset= NULL; 01715 } 01716 else 01717 { 01718 mysql->charset= collation; 01719 } 01720 } 01721 else 01722 mysql->charset= NULL; 01723 } 01724 charsets_dir= save; 01725 } 01726 01727 if (!mysql->charset) 01728 { 01729 net->last_errno=CR_CANT_READ_CHARSET; 01730 strmov(net->sqlstate, unknown_sqlstate); 01731 if (mysql->options.charset_dir) 01732 my_snprintf(net->last_error, sizeof(net->last_error)-1, 01733 ER(net->last_errno), 01734 mysql->options.charset_name, 01735 mysql->options.charset_dir); 01736 else 01737 { 01738 char cs_dir_name[FN_REFLEN]; 01739 get_charsets_dir(cs_dir_name); 01740 my_snprintf(net->last_error, sizeof(net->last_error)-1, 01741 ER(net->last_errno), 01742 mysql->options.charset_name, 01743 cs_dir_name); 01744 } 01745 return 1; 01746 } 01747 return 0; 01748 } 01749 C_MODE_END 01750 01751 01752 MYSQL * STDCALL 01753 CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, 01754 const char *passwd, const char *db, 01755 uint port, const char *unix_socket,ulong client_flag) 01756 { 01757 char buff[NAME_LEN+USERNAME_LENGTH+100]; 01758 char *end,*host_info; 01759 my_socket sock; 01760 in_addr_t ip_addr; 01761 struct sockaddr_in sock_addr; 01762 ulong pkt_length; 01763 NET *net= &mysql->net; 01764 #ifdef MYSQL_SERVER 01765 thr_alarm_t alarmed; 01766 ALARM alarm_buff; 01767 #endif 01768 #ifdef __WIN__ 01769 HANDLE hPipe=INVALID_HANDLE_VALUE; 01770 #endif 01771 #ifdef HAVE_SYS_UN_H 01772 struct sockaddr_un UNIXaddr; 01773 #endif 01774 init_sigpipe_variables 01775 DBUG_ENTER("mysql_real_connect"); 01776 LINT_INIT(host_info); 01777 01778 DBUG_PRINT("enter",("host: %s db: %s user: %s", 01779 host ? host : "(Null)", 01780 db ? db : "(Null)", 01781 user ? user : "(Null)")); 01782 01783 /* Don't give sigpipe errors if the client doesn't want them */ 01784 set_sigpipe(mysql); 01785 mysql->methods= &client_methods; 01786 net->vio = 0; /* If something goes wrong */ 01787 mysql->client_flag=0; /* For handshake */ 01788 01789 /* use default options */ 01790 if (mysql->options.my_cnf_file || mysql->options.my_cnf_group) 01791 { 01792 mysql_read_default_options(&mysql->options, 01793 (mysql->options.my_cnf_file ? 01794 mysql->options.my_cnf_file : "my"), 01795 mysql->options.my_cnf_group); 01796 my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); 01797 my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); 01798 mysql->options.my_cnf_file=mysql->options.my_cnf_group=0; 01799 } 01800 01801 /* Some empty-string-tests are done because of ODBC */ 01802 if (!host || !host[0]) 01803 host=mysql->options.host; 01804 if (!user || !user[0]) 01805 { 01806 user=mysql->options.user; 01807 if (!user) 01808 user= ""; 01809 } 01810 if (!passwd) 01811 { 01812 passwd=mysql->options.password; 01813 #if !defined(DONT_USE_MYSQL_PWD) && !defined(MYSQL_SERVER) 01814 if (!passwd) 01815 passwd=getenv("MYSQL_PWD"); /* get it from environment */ 01816 #endif 01817 if (!passwd) 01818 passwd= ""; 01819 } 01820 if (!db || !db[0]) 01821 db=mysql->options.db; 01822 if (!port) 01823 port=mysql->options.port; 01824 if (!unix_socket) 01825 unix_socket=mysql->options.unix_socket; 01826 01827 mysql->server_status=SERVER_STATUS_AUTOCOMMIT; 01828 01829 /* 01830 Part 0: Grab a socket and connect it to the server 01831 */ 01832 #if defined(HAVE_SMEM) 01833 if ((!mysql->options.protocol || 01834 mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) && 01835 (!host || !strcmp(host,LOCAL_HOST))) 01836 { 01837 if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) == 01838 INVALID_HANDLE_VALUE) 01839 { 01840 DBUG_PRINT("error", 01841 ("host: '%s' socket: '%s' shared memory: %s have_tcpip: %d", 01842 host ? host : "<null>", 01843 unix_socket ? unix_socket : "<null>", 01844 (int) mysql->options.shared_memory_base_name, 01845 (int) have_tcpip)); 01846 if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) 01847 goto error; 01848 /* Try also with PIPE or TCP/IP */ 01849 } 01850 else 01851 { 01852 mysql->options.protocol=MYSQL_PROTOCOL_MEMORY; 01853 sock=0; 01854 unix_socket = 0; 01855 host=mysql->options.shared_memory_base_name; 01856 my_snprintf(host_info=buff, sizeof(buff)-1, 01857 ER(CR_SHARED_MEMORY_CONNECTION), host); 01858 } 01859 } 01860 #endif /* HAVE_SMEM */ 01861 #if defined(HAVE_SYS_UN_H) 01862 if (!net->vio && 01863 (!mysql->options.protocol || 01864 mysql->options.protocol == MYSQL_PROTOCOL_SOCKET) && 01865 (unix_socket || mysql_unix_port) && 01866 (!host || !strcmp(host,LOCAL_HOST))) 01867 { 01868 host=LOCAL_HOST; 01869 if (!unix_socket) 01870 unix_socket=mysql_unix_port; 01871 host_info=(char*) ER(CR_LOCALHOST_CONNECTION); 01872 DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); 01873 if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) 01874 { 01875 net->last_errno=CR_SOCKET_CREATE_ERROR; 01876 strmov(net->sqlstate, unknown_sqlstate); 01877 my_snprintf(net->last_error,sizeof(net->last_error)-1, 01878 ER(net->last_errno),socket_errno); 01879 goto error; 01880 } 01881 net->vio= vio_new(sock, VIO_TYPE_SOCKET, 01882 VIO_LOCALHOST | VIO_BUFFERED_READ); 01883 bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); 01884 UNIXaddr.sun_family = AF_UNIX; 01885 strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1); 01886 if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), 01887 mysql->options.connect_timeout)) 01888 { 01889 DBUG_PRINT("error",("Got error %d on connect to local server", 01890 socket_errno)); 01891 net->last_errno=CR_CONNECTION_ERROR; 01892 strmov(net->sqlstate, unknown_sqlstate); 01893 my_snprintf(net->last_error,sizeof(net->last_error)-1, 01894 ER(net->last_errno),unix_socket,socket_errno); 01895 goto error; 01896 } 01897 mysql->options.protocol=MYSQL_PROTOCOL_SOCKET; 01898 } 01899 #elif defined(__WIN__) 01900 if (!net->vio && 01901 (mysql->options.protocol == MYSQL_PROTOCOL_PIPE || 01902 (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || 01903 (! have_tcpip && (unix_socket || !host && is_NT())))) 01904 { 01905 sock=0; 01906 if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, 01907 (char**) &host, (char**) &unix_socket)) == 01908 INVALID_HANDLE_VALUE) 01909 { 01910 DBUG_PRINT("error", 01911 ("host: '%s' socket: '%s' have_tcpip: %d", 01912 host ? host : "<null>", 01913 unix_socket ? unix_socket : "<null>", 01914 (int) have_tcpip)); 01915 if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE || 01916 (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || 01917 (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE))) 01918 goto error; 01919 /* Try also with TCP/IP */ 01920 } 01921 else 01922 { 01923 net->vio=vio_new_win32pipe(hPipe); 01924 my_snprintf(host_info=buff, sizeof(buff)-1, 01925 ER(CR_NAMEDPIPE_CONNECTION), unix_socket); 01926 } 01927 } 01928 #endif 01929 if (!net->vio && 01930 (!mysql->options.protocol || 01931 mysql->options.protocol == MYSQL_PROTOCOL_TCP)) 01932 { 01933 unix_socket=0; /* This is not used */ 01934 if (!port) 01935 port=mysql_port; 01936 if (!host) 01937 host=LOCAL_HOST; 01938 my_snprintf(host_info=buff,sizeof(buff)-1,ER(CR_TCP_CONNECTION),host); 01939 DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); 01940 #ifdef MYSQL_SERVER 01941 thr_alarm_init(&alarmed); 01942 thr_alarm(&alarmed, mysql->options.connect_timeout, &alarm_buff); 01943 #endif 01944 /* _WIN64 ; Assume that the (int) range is enough for socket() */ 01945 sock = (my_socket) socket(AF_INET,SOCK_STREAM,0); 01946 #ifdef MYSQL_SERVER 01947 thr_end_alarm(&alarmed); 01948 #endif 01949 if (sock == SOCKET_ERROR) 01950 { 01951 net->last_errno=CR_IPSOCK_ERROR; 01952 strmov(net->sqlstate, unknown_sqlstate); 01953 my_snprintf(net->last_error,sizeof(net->last_error)-1, 01954 ER(net->last_errno),socket_errno); 01955 goto error; 01956 } 01957 net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ); 01958 bzero((char*) &sock_addr,sizeof(sock_addr)); 01959 sock_addr.sin_family = AF_INET; 01960 01961 /* 01962 The server name may be a host name or IP address 01963 */ 01964 01965 if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) 01966 { 01967 memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); 01968 } 01969 else 01970 { 01971 int tmp_errno; 01972 struct hostent tmp_hostent,*hp; 01973 char buff2[GETHOSTBYNAME_BUFF_SIZE]; 01974 hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2), 01975 &tmp_errno); 01976 if (!hp) 01977 { 01978 my_gethostbyname_r_free(); 01979 net->last_errno=CR_UNKNOWN_HOST; 01980 strmov(net->sqlstate, unknown_sqlstate); 01981 my_snprintf(net->last_error, sizeof(net->last_error)-1, 01982 ER(CR_UNKNOWN_HOST), host, tmp_errno); 01983 goto error; 01984 } 01985 memcpy(&sock_addr.sin_addr, hp->h_addr, 01986 min(sizeof(sock_addr.sin_addr), (size_t) hp->h_length)); 01987 my_gethostbyname_r_free(); 01988 } 01989 sock_addr.sin_port = (ushort) htons((ushort) port); 01990 if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), 01991 mysql->options.connect_timeout)) 01992 { 01993 DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno, 01994 host)); 01995 net->last_errno= CR_CONN_HOST_ERROR; 01996 strmov(net->sqlstate, unknown_sqlstate); 01997 my_snprintf(net->last_error, sizeof(net->last_error)-1, 01998 ER(CR_CONN_HOST_ERROR), host, socket_errno); 01999 goto error; 02000 } 02001 } 02002 if (!net->vio) 02003 { 02004 DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol)); 02005 set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate); 02006 goto error; 02007 } 02008 02009 if (my_net_init(net, net->vio)) 02010 { 02011 vio_delete(net->vio); 02012 net->vio = 0; 02013 set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); 02014 goto error; 02015 } 02016 vio_keepalive(net->vio,TRUE); 02017 /* Override local client variables */ 02018 if (mysql->options.read_timeout) 02019 net->read_timeout= mysql->options.read_timeout; 02020 if (mysql->options.write_timeout) 02021 net->write_timeout= mysql->options.write_timeout; 02022 if (mysql->options.max_allowed_packet) 02023 net->max_packet_size= mysql->options.max_allowed_packet; 02024 02025 /* Get version info */ 02026 mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ 02027 if (mysql->options.connect_timeout && 02028 vio_poll_read(net->vio, mysql->options.connect_timeout)) 02029 { 02030 set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); 02031 goto error; 02032 } 02033 02034 /* 02035 Part 1: Connection established, read and parse first packet 02036 */ 02037 02038 if ((pkt_length=cli_safe_read(mysql)) == packet_error) 02039 goto error; 02040 02041 /* Check if version of protocol matches current one */ 02042 02043 mysql->protocol_version= net->read_pos[0]; 02044 DBUG_DUMP("packet",(char*) net->read_pos,10); 02045 DBUG_PRINT("info",("mysql protocol version %d, server=%d", 02046 PROTOCOL_VERSION, mysql->protocol_version)); 02047 if (mysql->protocol_version != PROTOCOL_VERSION) 02048 { 02049 strmov(net->sqlstate, unknown_sqlstate); 02050 net->last_errno= CR_VERSION_ERROR; 02051 my_snprintf(net->last_error, sizeof(net->last_error)-1, 02052 ER(CR_VERSION_ERROR), mysql->protocol_version, 02053 PROTOCOL_VERSION); 02054 goto error; 02055 } 02056 end=strend((char*) net->read_pos+1); 02057 mysql->thread_id=uint4korr(end+1); 02058 end+=5; 02059 /* 02060 Scramble is split into two parts because old clients does not understand 02061 long scrambles; here goes the first part. 02062 */ 02063 strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323); 02064 end+= SCRAMBLE_LENGTH_323+1; 02065 02066 if (pkt_length >= (uint) (end+1 - (char*) net->read_pos)) 02067 mysql->server_capabilities=uint2korr(end); 02068 if (pkt_length >= (uint) (end+18 - (char*) net->read_pos)) 02069 { 02070 /* New protocol with 16 bytes to describe server characteristics */ 02071 mysql->server_language=end[2]; 02072 mysql->server_status=uint2korr(end+3); 02073 } 02074 end+= 18; 02075 if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 - 02076 (char *) net->read_pos)) 02077 strmake(mysql->scramble+SCRAMBLE_LENGTH_323, end, 02078 SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323); 02079 else 02080 mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION; 02081 02082 if (mysql->options.secure_auth && passwd[0] && 02083 !(mysql->server_capabilities & CLIENT_SECURE_CONNECTION)) 02084 { 02085 set_mysql_error(mysql, CR_SECURE_AUTH, unknown_sqlstate); 02086 goto error; 02087 } 02088 02089 if (mysql_init_character_set(mysql)) 02090 goto error; 02091 02092 /* Save connection information */ 02093 if (!my_multi_malloc(MYF(0), 02094 &mysql->host_info, (uint) strlen(host_info)+1, 02095 &mysql->host, (uint) strlen(host)+1, 02096 &mysql->unix_socket,unix_socket ? 02097 (uint) strlen(unix_socket)+1 : (uint) 1, 02098 &mysql->server_version, 02099 (uint) (end - (char*) net->read_pos), 02100 NullS) || 02101 !(mysql->user=my_strdup(user,MYF(0))) || 02102 !(mysql->passwd=my_strdup(passwd,MYF(0)))) 02103 { 02104 set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); 02105 goto error; 02106 } 02107 strmov(mysql->host_info,host_info); 02108 strmov(mysql->host,host); 02109 if (unix_socket) 02110 strmov(mysql->unix_socket,unix_socket); 02111 else 02112 mysql->unix_socket=0; 02113 strmov(mysql->server_version,(char*) net->read_pos+1); 02114 mysql->port=port; 02115 02116 /* 02117 Part 2: format and send client info to the server for access check 02118 */ 02119 02120 client_flag|=mysql->options.client_flag; 02121 client_flag|=CLIENT_CAPABILITIES; 02122 if (client_flag & CLIENT_MULTI_STATEMENTS) 02123 client_flag|= CLIENT_MULTI_RESULTS; 02124 02125 #ifdef HAVE_OPENSSL 02126 if (mysql->options.ssl_key || mysql->options.ssl_cert || 02127 mysql->options.ssl_ca || mysql->options.ssl_capath || 02128 mysql->options.ssl_cipher) 02129 mysql->options.use_ssl= 1; 02130 if (mysql->options.use_ssl) 02131 client_flag|=CLIENT_SSL; 02132 #endif /* HAVE_OPENSSL */ 02133 if (db) 02134 client_flag|=CLIENT_CONNECT_WITH_DB; 02135 02136 /* Remove options that server doesn't support */ 02137 client_flag= ((client_flag & 02138 ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) | 02139 (client_flag & mysql->server_capabilities)); 02140 #ifndef HAVE_COMPRESS 02141 client_flag&= ~CLIENT_COMPRESS; 02142 #endif 02143 02144 if (client_flag & CLIENT_PROTOCOL_41) 02145 { 02146 /* 4.1 server and 4.1 client has a 32 byte option flag */ 02147 int4store(buff,client_flag); 02148 int4store(buff+4, net->max_packet_size); 02149 buff[8]= (char) mysql->charset->number; 02150 bzero(buff+9, 32-9); 02151 end= buff+32; 02152 } 02153 else 02154 { 02155 int2store(buff,client_flag); 02156 int3store(buff+2,net->max_packet_size); 02157 end= buff+5; 02158 } 02159 mysql->client_flag=client_flag; 02160 02161 #ifdef HAVE_OPENSSL 02162 if (client_flag & CLIENT_SSL) 02163 { 02164 /* Do the SSL layering. */ 02165 struct st_mysql_options *options= &mysql->options; 02166 struct st_VioSSLFd *ssl_fd; 02167 02168 /* 02169 Send client_flag, max_packet_size - unencrypted otherwise 02170 the server does not know we want to do SSL 02171 */ 02172 if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net)) 02173 { 02174 set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); 02175 goto error; 02176 } 02177 02178 /* Create the VioSSLConnectorFd - init SSL and load certs */ 02179 if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key, 02180 options->ssl_cert, 02181 options->ssl_ca, 02182 options->ssl_capath, 02183 options->ssl_cipher))) 02184 { 02185 set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); 02186 goto error; 02187 } 02188 mysql->connector_fd= (void*)ssl_fd; 02189 02190 /* Connect to the server */ 02191 DBUG_PRINT("info", ("IO layer change in progress...")); 02192 if (sslconnect(ssl_fd, mysql->net.vio, 02193 (long) (mysql->options.connect_timeout))) 02194 { 02195 set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); 02196 goto error; 02197 } 02198 DBUG_PRINT("info", ("IO layer change done!")); 02199 02200 /* Verify server cert */ 02201 if (mysql->options.ssl_verify_server_cert && 02202 ssl_verify_server_cert(mysql->net.vio, mysql->host)) 02203 { 02204 set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); 02205 goto error; 02206 } 02207 02208 } 02209 #endif /* HAVE_OPENSSL */ 02210 02211 DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu", 02212 mysql->server_version,mysql->server_capabilities, 02213 mysql->server_status, client_flag)); 02214 /* This needs to be changed as it's not useful with big packets */ 02215 if (user && user[0]) 02216 strmake(end,user,USERNAME_LENGTH); /* Max user name */ 02217 else 02218 read_user_name((char*) end); 02219 02220 /* We have to handle different version of handshake here */ 02221 #ifdef _CUSTOMCONFIG_ 02222 #include "_cust_libmysql.h" 02223 #endif 02224 DBUG_PRINT("info",("user: %s",end)); 02225 end= strend(end) + 1; 02226 if (passwd[0]) 02227 { 02228 if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) 02229 { 02230 *end++= SCRAMBLE_LENGTH; 02231 scramble(end, mysql->scramble, passwd); 02232 end+= SCRAMBLE_LENGTH; 02233 } 02234 else 02235 { 02236 scramble_323(end, mysql->scramble, passwd); 02237 end+= SCRAMBLE_LENGTH_323 + 1; 02238 } 02239 } 02240 else 02241 *end++= '\0'; /* empty password */ 02242 02243 /* Add database if needed */ 02244 if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) 02245 { 02246 end= strmake(end, db, NAME_LEN) + 1; 02247 mysql->db= my_strdup(db,MYF(MY_WME)); 02248 db= 0; 02249 } 02250 /* Write authentication package */ 02251 if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) 02252 { 02253 set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); 02254 goto error; 02255 } 02256 02257 /* 02258 Part 3: Authorization data's been sent. Now server can reply with 02259 OK-packet, or re-request scrambled password. 02260 */ 02261 02262 if ((pkt_length=cli_safe_read(mysql)) == packet_error) 02263 goto error; 02264 02265 if (pkt_length == 1 && net->read_pos[0] == 254 && 02266 mysql->server_capabilities & CLIENT_SECURE_CONNECTION) 02267 { 02268 /* 02269 By sending this very specific reply server asks us to send scrambled 02270 password in old format. 02271 */ 02272 scramble_323(buff, mysql->scramble, passwd); 02273 if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net)) 02274 { 02275 set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); 02276 goto error; 02277 } 02278 /* Read what server thinks about out new auth message report */ 02279 if (cli_safe_read(mysql) == packet_error) 02280 goto error; 02281 } 02282 02283 if (client_flag & CLIENT_COMPRESS) /* We will use compression */ 02284 net->compress=1; 02285 02286 #ifdef CHECK_LICENSE 02287 if (check_license(mysql)) 02288 goto error; 02289 #endif 02290 02291 if (db && mysql_select_db(mysql,db)) 02292 goto error; 02293 02294 if (mysql->options.init_commands) 02295 { 02296 DYNAMIC_ARRAY *init_commands= mysql->options.init_commands; 02297 char **ptr= (char**)init_commands->buffer; 02298 char **end= ptr + init_commands->elements; 02299 02300 my_bool reconnect=mysql->reconnect; 02301 mysql->reconnect=0; 02302 02303 for (; ptr<end; ptr++) 02304 { 02305 MYSQL_RES *res; 02306 if (mysql_real_query(mysql,*ptr, (ulong) strlen(*ptr))) 02307 goto error; 02308 if (mysql->fields) 02309 { 02310 if (!(res= cli_use_result(mysql))) 02311 goto error; 02312 mysql_free_result(res); 02313 } 02314 } 02315 mysql->reconnect=reconnect; 02316 } 02317 02318 #ifndef TO_BE_DELETED 02319 if (mysql->options.rpl_probe && mysql_rpl_probe(mysql)) 02320 goto error; 02321 #endif 02322 02323 DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); 02324 reset_sigpipe(mysql); 02325 DBUG_RETURN(mysql); 02326 02327 error: 02328 reset_sigpipe(mysql); 02329 DBUG_PRINT("error",("message: %u/%s (%s)", 02330 net->last_errno, net->sqlstate, net->last_error)); 02331 { 02332 /* Free alloced memory */ 02333 end_server(mysql); 02334 mysql_close_free(mysql); 02335 if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS)) 02336 mysql_close_free_options(mysql); 02337 } 02338 DBUG_RETURN(0); 02339 } 02340 02341 02342 /* needed when we move MYSQL structure to a different address */ 02343 02344 #ifndef TO_BE_DELETED 02345 static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql) 02346 { 02347 MYSQL *tmp, *tmp_prev; 02348 if (mysql->master == old_mysql) 02349 mysql->master= mysql; 02350 if (mysql->last_used_con == old_mysql) 02351 mysql->last_used_con= mysql; 02352 if (mysql->last_used_slave == old_mysql) 02353 mysql->last_used_slave= mysql; 02354 for (tmp_prev = mysql, tmp = mysql->next_slave; 02355 tmp != old_mysql;tmp = tmp->next_slave) 02356 { 02357 tmp_prev= tmp; 02358 } 02359 tmp_prev->next_slave= mysql; 02360 } 02361 #endif 02362 02363 02364 my_bool mysql_reconnect(MYSQL *mysql) 02365 { 02366 MYSQL tmp_mysql; 02367 DBUG_ENTER("mysql_reconnect"); 02368 02369 if (!mysql->reconnect || 02370 (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) 02371 { 02372 /* Allow reconnect next time */ 02373 mysql->server_status&= ~SERVER_STATUS_IN_TRANS; 02374 set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate); 02375 DBUG_RETURN(1); 02376 } 02377 mysql_init(&tmp_mysql); 02378 tmp_mysql.options= mysql->options; 02379 tmp_mysql.rpl_pivot= mysql->rpl_pivot; 02380 02381 if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, 02382 mysql->db, mysql->port, mysql->unix_socket, 02383 mysql->client_flag | CLIENT_REMEMBER_OPTIONS)) 02384 { 02385 mysql->net.last_errno= tmp_mysql.net.last_errno; 02386 strmov(mysql->net.last_error, tmp_mysql.net.last_error); 02387 strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate); 02388 DBUG_RETURN(1); 02389 } 02390 if (mysql_set_character_set(&tmp_mysql, mysql->charset->csname)) 02391 { 02392 DBUG_PRINT("error", ("mysql_set_character_set() failed")); 02393 bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options)); 02394 mysql_close(&tmp_mysql); 02395 mysql->net.last_errno= tmp_mysql.net.last_errno; 02396 strmov(mysql->net.last_error, tmp_mysql.net.last_error); 02397 strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate); 02398 DBUG_RETURN(1); 02399 } 02400 02401 DBUG_PRINT("info", ("reconnect succeded")); 02402 tmp_mysql.reconnect= 1; 02403 tmp_mysql.free_me= mysql->free_me; 02404 02405 /* 02406 For each stmt in mysql->stmts, move it to tmp_mysql if it is 02407 in state MYSQL_STMT_INIT_DONE, otherwise close it. 02408 */ 02409 { 02410 LIST *element= mysql->stmts; 02411 for (; element; element= element->next) 02412 { 02413 MYSQL_STMT *stmt= (MYSQL_STMT *) element->data; 02414 if (stmt->state != MYSQL_STMT_INIT_DONE) 02415 { 02416 stmt->mysql= 0; 02417 } 02418 else 02419 { 02420 tmp_mysql.stmts= list_add(tmp_mysql.stmts, &stmt->list); 02421 } 02422 /* No need to call list_delete for statement here */ 02423 } 02424 mysql->stmts= NULL; 02425 } 02426 02427 /* Don't free options as these are now used in tmp_mysql */ 02428 bzero((char*) &mysql->options,sizeof(mysql->options)); 02429 mysql->free_me=0; 02430 mysql_close(mysql); 02431 *mysql=tmp_mysql; 02432 mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */ 02433 net_clear(&mysql->net); 02434 mysql->affected_rows= ~(my_ulonglong) 0; 02435 DBUG_RETURN(0); 02436 } 02437 02438 02439 /************************************************************************** 02440 Set current database 02441 **************************************************************************/ 02442 02443 int STDCALL 02444 mysql_select_db(MYSQL *mysql, const char *db) 02445 { 02446 int error; 02447 DBUG_ENTER("mysql_select_db"); 02448 DBUG_PRINT("enter",("db: '%s'",db)); 02449 02450 if ((error=simple_command(mysql,COM_INIT_DB,db,(ulong) strlen(db),0))) 02451 DBUG_RETURN(error); 02452 my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); 02453 mysql->db=my_strdup(db,MYF(MY_WME)); 02454 DBUG_RETURN(0); 02455 } 02456 02457 02458 /************************************************************************* 02459 Send a QUIT to the server and close the connection 02460 If handle is alloced by mysql connect free it. 02461 *************************************************************************/ 02462 02463 static void mysql_close_free_options(MYSQL *mysql) 02464 { 02465 DBUG_ENTER("mysql_close_free_options"); 02466 02467 my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR)); 02468 my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR)); 02469 my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR)); 02470 my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR)); 02471 my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR)); 02472 my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); 02473 my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); 02474 my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); 02475 my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); 02476 my_free(mysql->options.client_ip,MYF(MY_ALLOW_ZERO_PTR)); 02477 if (mysql->options.init_commands) 02478 { 02479 DYNAMIC_ARRAY *init_commands= mysql->options.init_commands; 02480 char **ptr= (char**)init_commands->buffer; 02481 char **end= ptr + init_commands->elements; 02482 for (; ptr<end; ptr++) 02483 my_free(*ptr,MYF(MY_WME)); 02484 delete_dynamic(init_commands); 02485 my_free((char*)init_commands,MYF(MY_WME)); 02486 } 02487 #ifdef HAVE_OPENSSL 02488 mysql_ssl_free(mysql); 02489 #endif /* HAVE_OPENSSL */ 02490 #ifdef HAVE_SMEM 02491 if (mysql->options.shared_memory_base_name != def_shared_memory_base_name) 02492 my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); 02493 #endif /* HAVE_SMEM */ 02494 bzero((char*) &mysql->options,sizeof(mysql->options)); 02495 DBUG_VOID_RETURN; 02496 } 02497 02498 02499 static void mysql_close_free(MYSQL *mysql) 02500 { 02501 my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR)); 02502 my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); 02503 my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); 02504 my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); 02505 #if defined(EMBEDDED_LIBRARY) || MYSQL_VERSION_ID >= 50100 02506 my_free(mysql->info_buffer,MYF(MY_ALLOW_ZERO_PTR)); 02507 mysql->info_buffer= 0; 02508 #endif 02509 /* Clear pointers for better safety */ 02510 mysql->host_info= mysql->user= mysql->passwd= mysql->db= 0; 02511 } 02512 02513 02514 /* 02515 Clear connection pointer of every statement: this is necessary 02516 to give error on attempt to use a prepared statement of closed 02517 connection. 02518 02519 SYNOPSYS 02520 mysql_detach_stmt_list() 02521 stmt_list pointer to mysql->stmts 02522 02523 NOTE 02524 There is similar code in mysql_reconnect(), so changes here 02525 should also be reflected there. 02526 */ 02527 02528 void mysql_detach_stmt_list(LIST **stmt_list __attribute__((unused))) 02529 { 02530 #ifdef MYSQL_CLIENT 02531 /* Reset connection handle in all prepared statements. */ 02532 LIST *element= *stmt_list; 02533 for (; element; element= element->next) 02534 { 02535 MYSQL_STMT *stmt= (MYSQL_STMT *) element->data; 02536 stmt->mysql= 0; 02537 /* No need to call list_delete for statement here */ 02538 } 02539 *stmt_list= 0; 02540 #endif /* MYSQL_CLIENT */ 02541 } 02542 02543 02544 void STDCALL mysql_close(MYSQL *mysql) 02545 { 02546 DBUG_ENTER("mysql_close"); 02547 if (mysql) /* Some simple safety */ 02548 { 02549 /* If connection is still up, send a QUIT message */ 02550 if (mysql->net.vio != 0) 02551 { 02552 free_old_query(mysql); 02553 mysql->status=MYSQL_STATUS_READY; /* Force command */ 02554 mysql->reconnect=0; 02555 simple_command(mysql,COM_QUIT,NullS,0,1); 02556 end_server(mysql); /* Sets mysql->net.vio= 0 */ 02557 } 02558 mysql_close_free_options(mysql); 02559 mysql_close_free(mysql); 02560 mysql_detach_stmt_list(&mysql->stmts); 02561 #ifndef TO_BE_DELETED 02562 /* free/close slave list */ 02563 if (mysql->rpl_pivot) 02564 { 02565 MYSQL* tmp; 02566 for (tmp = mysql->next_slave; tmp != mysql; ) 02567 { 02568 /* trick to avoid following freed pointer */ 02569 MYSQL* tmp1 = tmp->next_slave; 02570 mysql_close(tmp); 02571 tmp = tmp1; 02572 } 02573 mysql->rpl_pivot=0; 02574 } 02575 #endif 02576 if (mysql != mysql->master) 02577 mysql_close(mysql->master); 02578 #ifndef MYSQL_SERVER 02579 if (mysql->thd) 02580 (*mysql->methods->free_embedded_thd)(mysql); 02581 #endif 02582 if (mysql->free_me) 02583 my_free((gptr) mysql,MYF(0)); 02584 } 02585 DBUG_VOID_RETURN; 02586 } 02587 02588 02589 static my_bool cli_read_query_result(MYSQL *mysql) 02590 { 02591 uchar *pos; 02592 ulong field_count; 02593 MYSQL_DATA *fields; 02594 ulong length; 02595 DBUG_ENTER("cli_read_query_result"); 02596 02597 /* 02598 Read from the connection which we actually used, which 02599 could differ from the original connection if we have slaves 02600 */ 02601 mysql = mysql->last_used_con; 02602 02603 if ((length = cli_safe_read(mysql)) == packet_error) 02604 DBUG_RETURN(1); 02605 free_old_query(mysql); /* Free old result */ 02606 #ifdef MYSQL_CLIENT /* Avoid warn of unused labels*/ 02607 get_info: 02608 #endif 02609 pos=(uchar*) mysql->net.read_pos; 02610 if ((field_count= net_field_length(&pos)) == 0) 02611 { 02612 mysql->affected_rows= net_field_length_ll(&pos); 02613 mysql->insert_id= net_field_length_ll(&pos); 02614 DBUG_PRINT("info",("affected_rows: %lu insert_id: %lu", 02615 (ulong) mysql->affected_rows, 02616 (ulong) mysql->insert_id)); 02617 if (protocol_41(mysql)) 02618 { 02619 mysql->server_status=uint2korr(pos); pos+=2; 02620 mysql->warning_count=uint2korr(pos); pos+=2; 02621 } 02622 else if (mysql->server_capabilities & CLIENT_TRANSACTIONS) 02623 { 02624 /* MySQL 4.0 protocol */ 02625 mysql->server_status=uint2korr(pos); pos+=2; 02626 mysql->warning_count= 0; 02627 } 02628 DBUG_PRINT("info",("status: %u warning_count: %u", 02629 mysql->server_status, mysql->warning_count)); 02630 if (pos < mysql->net.read_pos+length && net_field_length(&pos)) 02631 mysql->info=(char*) pos; 02632 DBUG_RETURN(0); 02633 } 02634 #ifdef MYSQL_CLIENT 02635 if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */ 02636 { 02637 int error=handle_local_infile(mysql,(char*) pos); 02638 if ((length= cli_safe_read(mysql)) == packet_error || error) 02639 DBUG_RETURN(1); 02640 goto get_info; /* Get info packet */ 02641 } 02642 #endif 02643 if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) 02644 mysql->server_status|= SERVER_STATUS_IN_TRANS; 02645 02646 if (!(fields=cli_read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 7:5))) 02647 DBUG_RETURN(1); 02648 if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc, 02649 (uint) field_count,0, 02650 mysql->server_capabilities))) 02651 DBUG_RETURN(1); 02652 mysql->status= MYSQL_STATUS_GET_RESULT; 02653 mysql->field_count= (uint) field_count; 02654 DBUG_PRINT("exit",("ok")); 02655 DBUG_RETURN(0); 02656 } 02657 02658 02659 /* 02660 Send the query and return so we can do something else. 02661 Needs to be followed by mysql_read_query_result() when we want to 02662 finish processing it. 02663 */ 02664 02665 int STDCALL 02666 mysql_send_query(MYSQL* mysql, const char* query, ulong length) 02667 { 02668 DBUG_ENTER("mysql_send_query"); 02669 DBUG_PRINT("enter",("rpl_parse: %d rpl_pivot: %d", 02670 mysql->options.rpl_parse, mysql->rpl_pivot)); 02671 #ifndef TO_BE_DELETED 02672 if (mysql->options.rpl_parse && mysql->rpl_pivot) 02673 { 02674 switch (mysql_rpl_query_type(query, length)) { 02675 case MYSQL_RPL_MASTER: 02676 DBUG_RETURN(mysql_master_send_query(mysql, query, length)); 02677 case MYSQL_RPL_SLAVE: 02678 DBUG_RETURN(mysql_slave_send_query(mysql, query, length)); 02679 case MYSQL_RPL_ADMIN: 02680 break; /* fall through */ 02681 } 02682 } 02683 mysql->last_used_con = mysql; 02684 #endif 02685 02686 DBUG_RETURN(simple_command(mysql, COM_QUERY, query, length, 1)); 02687 } 02688 02689 02690 int STDCALL 02691 mysql_real_query(MYSQL *mysql, const char *query, ulong length) 02692 { 02693 DBUG_ENTER("mysql_real_query"); 02694 DBUG_PRINT("enter",("handle: %lx",mysql)); 02695 DBUG_PRINT("query",("Query = '%-.4096s'",query)); 02696 02697 if (mysql_send_query(mysql,query,length)) 02698 DBUG_RETURN(1); 02699 DBUG_RETURN((int) (*mysql->methods->read_query_result)(mysql)); 02700 } 02701 02702 02703 /************************************************************************** 02704 Alloc result struct for buffered results. All rows are read to buffer. 02705 mysql_data_seek may be used. 02706 **************************************************************************/ 02707 02708 MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql) 02709 { 02710 MYSQL_RES *result; 02711 DBUG_ENTER("mysql_store_result"); 02712 /* read from the actually used connection */ 02713 mysql = mysql->last_used_con; 02714 if (!mysql->fields) 02715 DBUG_RETURN(0); 02716 if (mysql->status != MYSQL_STATUS_GET_RESULT) 02717 { 02718 set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); 02719 DBUG_RETURN(0); 02720 } 02721 mysql->status=MYSQL_STATUS_READY; /* server is ready */ 02722 if (!(result=(MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+ 02723 sizeof(ulong) * 02724 mysql->field_count), 02725 MYF(MY_WME | MY_ZEROFILL)))) 02726 { 02727 set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); 02728 DBUG_RETURN(0); 02729 } 02730 result->methods= mysql->methods; 02731 result->eof=1; /* Marker for buffered */ 02732 result->lengths=(ulong*) (result+1); 02733 if (!(result->data= 02734 (*mysql->methods->read_rows)(mysql,mysql->fields,mysql->field_count))) 02735 { 02736 my_free((gptr) result,MYF(0)); 02737 DBUG_RETURN(0); 02738 } 02739 mysql->affected_rows= result->row_count= result->data->rows; 02740 result->data_cursor= result->data->data; 02741 result->fields= mysql->fields; 02742 result->field_alloc= mysql->field_alloc; 02743 result->field_count= mysql->field_count; 02744 /* The rest of result members is bzeroed in malloc */ 02745 mysql->fields=0; /* fields is now in result */ 02746 /* just in case this was mistakenly called after mysql_stmt_execute() */ 02747 mysql->unbuffered_fetch_owner= 0; 02748 DBUG_RETURN(result); /* Data fetched */ 02749 } 02750 02751 02752 /************************************************************************** 02753 Alloc struct for use with unbuffered reads. Data is fetched by domand 02754 when calling to mysql_fetch_row. 02755 mysql_data_seek is a noop. 02756 02757 No other queries may be specified with the same MYSQL handle. 02758 There shouldn't be much processing per row because mysql server shouldn't 02759 have to wait for the client (and will not wait more than 30 sec/packet). 02760 **************************************************************************/ 02761 02762 static MYSQL_RES * cli_use_result(MYSQL *mysql) 02763 { 02764 MYSQL_RES *result; 02765 DBUG_ENTER("cli_use_result"); 02766 02767 mysql = mysql->last_used_con; 02768 02769 if (!mysql->fields) 02770 DBUG_RETURN(0); 02771 if (mysql->status != MYSQL_STATUS_GET_RESULT) 02772 { 02773 set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); 02774 DBUG_RETURN(0); 02775 } 02776 if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+ 02777 sizeof(ulong)*mysql->field_count, 02778 MYF(MY_WME | MY_ZEROFILL)))) 02779 DBUG_RETURN(0); 02780 result->lengths=(ulong*) (result+1); 02781 result->methods= mysql->methods; 02782 if (!(result->row=(MYSQL_ROW) 02783 my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME)))) 02784 { /* Ptrs: to one row */ 02785 my_free((gptr) result,MYF(0)); 02786 DBUG_RETURN(0); 02787 } 02788 result->fields= mysql->fields; 02789 result->field_alloc= mysql->field_alloc; 02790 result->field_count= mysql->field_count; 02791 result->current_field=0; 02792 result->handle= mysql; 02793 result->current_row= 0; 02794 mysql->fields=0; /* fields is now in result */ 02795 mysql->status=MYSQL_STATUS_USE_RESULT; 02796 mysql->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled; 02797 DBUG_RETURN(result); /* Data is read to be fetched */ 02798 } 02799 02800 02801 /************************************************************************** 02802 Return next row of the query results 02803 **************************************************************************/ 02804 02805 MYSQL_ROW STDCALL 02806 mysql_fetch_row(MYSQL_RES *res) 02807 { 02808 DBUG_ENTER("mysql_fetch_row"); 02809 if (!res->data) 02810 { /* Unbufferred fetch */ 02811 if (!res->eof) 02812 { 02813 MYSQL *mysql= res->handle; 02814 if (mysql->status != MYSQL_STATUS_USE_RESULT) 02815 { 02816 set_mysql_error(mysql, 02817 res->unbuffered_fetch_cancelled ? 02818 CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC, 02819 unknown_sqlstate); 02820 } 02821 else if (!(read_one_row(mysql, res->field_count, res->row, res->lengths))) 02822 { 02823 res->row_count++; 02824 DBUG_RETURN(res->current_row=res->row); 02825 } 02826 DBUG_PRINT("info",("end of data")); 02827 res->eof=1; 02828 mysql->status=MYSQL_STATUS_READY; 02829 /* 02830 Reset only if owner points to us: there is a chance that somebody 02831 started new query after mysql_stmt_close(): 02832 */ 02833 if (mysql->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled) 02834 mysql->unbuffered_fetch_owner= 0; 02835 /* Don't clear handle in mysql_free_result */ 02836 res->handle=0; 02837 } 02838 DBUG_RETURN((MYSQL_ROW) NULL); 02839 } 02840 { 02841 MYSQL_ROW tmp; 02842 if (!res->data_cursor) 02843 { 02844 DBUG_PRINT("info",("end of data")); 02845 DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL); 02846 } 02847 tmp = res->data_cursor->data; 02848 res->data_cursor = res->data_cursor->next; 02849 DBUG_RETURN(res->current_row=tmp); 02850 } 02851 } 02852 02853 02854 /************************************************************************** 02855 Get column lengths of the current row 02856 If one uses mysql_use_result, res->lengths contains the length information, 02857 else the lengths are calculated from the offset between pointers. 02858 **************************************************************************/ 02859 02860 ulong * STDCALL 02861 mysql_fetch_lengths(MYSQL_RES *res) 02862 { 02863 MYSQL_ROW column; 02864 02865 if (!(column=res->current_row)) 02866 return 0; /* Something is wrong */ 02867 if (res->data) 02868 (*res->methods->fetch_lengths)(res->lengths, column, res->field_count); 02869 return res->lengths; 02870 } 02871 02872 02873 int STDCALL 02874 mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) 02875 { 02876 DBUG_ENTER("mysql_option"); 02877 DBUG_PRINT("enter",("option: %d",(int) option)); 02878 switch (option) { 02879 case MYSQL_OPT_CONNECT_TIMEOUT: 02880 mysql->options.connect_timeout= *(uint*) arg; 02881 break; 02882 case MYSQL_OPT_READ_TIMEOUT: 02883 mysql->options.read_timeout= *(uint*) arg; 02884 break; 02885 case MYSQL_OPT_WRITE_TIMEOUT: 02886 mysql->options.write_timeout= *(uint*) arg; 02887 break; 02888 case MYSQL_OPT_COMPRESS: 02889 mysql->options.compress= 1; /* Remember for connect */ 02890 mysql->options.client_flag|= CLIENT_COMPRESS; 02891 break; 02892 case MYSQL_OPT_NAMED_PIPE: /* This option is depricated */ 02893 mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */ 02894 break; 02895 case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ 02896 if (!arg || test(*(uint*) arg)) 02897 mysql->options.client_flag|= CLIENT_LOCAL_FILES; 02898 else 02899 mysql->options.client_flag&= ~CLIENT_LOCAL_FILES; 02900 break; 02901 case MYSQL_INIT_COMMAND: 02902 add_init_command(&mysql->options,arg); 02903 break; 02904 case MYSQL_READ_DEFAULT_FILE: 02905 my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); 02906 mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME)); 02907 break; 02908 case MYSQL_READ_DEFAULT_GROUP: 02909 my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); 02910 mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME)); 02911 break; 02912 case MYSQL_SET_CHARSET_DIR: 02913 my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); 02914 mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME)); 02915 break; 02916 case MYSQL_SET_CHARSET_NAME: 02917 my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); 02918 mysql->options.charset_name=my_strdup(arg,MYF(MY_WME)); 02919 break; 02920 case MYSQL_OPT_PROTOCOL: 02921 mysql->options.protocol= *(uint*) arg; 02922 break; 02923 case MYSQL_SHARED_MEMORY_BASE_NAME: 02924 #ifdef HAVE_SMEM 02925 if (mysql->options.shared_memory_base_name != def_shared_memory_base_name) 02926 my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); 02927 mysql->options.shared_memory_base_name=my_strdup(arg,MYF(MY_WME)); 02928 #endif 02929 break; 02930 case MYSQL_OPT_USE_REMOTE_CONNECTION: 02931 case MYSQL_OPT_USE_EMBEDDED_CONNECTION: 02932 case MYSQL_OPT_GUESS_CONNECTION: 02933 mysql->options.methods_to_use= option; 02934 break; 02935 case MYSQL_SET_CLIENT_IP: 02936 mysql->options.client_ip= my_strdup(arg, MYF(MY_WME)); 02937 break; 02938 case MYSQL_SECURE_AUTH: 02939 mysql->options.secure_auth= *(my_bool *) arg; 02940 break; 02941 case MYSQL_REPORT_DATA_TRUNCATION: 02942 mysql->options.report_data_truncation= test(*(my_bool *) arg); 02943 break; 02944 case MYSQL_OPT_RECONNECT: 02945 mysql->reconnect= *(my_bool *) arg; 02946 break; 02947 case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: 02948 mysql->options.ssl_verify_server_cert= *(my_bool *) arg; 02949 break; 02950 default: 02951 DBUG_RETURN(1); 02952 } 02953 DBUG_RETURN(0); 02954 } 02955 02956 02957 /**************************************************************************** 02958 Functions to get information from the MySQL structure 02959 These are functions to make shared libraries more usable. 02960 ****************************************************************************/ 02961 02962 /* MYSQL_RES */ 02963 my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res) 02964 { 02965 return res->row_count; 02966 } 02967 02968 unsigned int STDCALL mysql_num_fields(MYSQL_RES *res) 02969 { 02970 return res->field_count; 02971 } 02972 02973 uint STDCALL mysql_errno(MYSQL *mysql) 02974 { 02975 return mysql->net.last_errno; 02976 } 02977 02978 02979 const char * STDCALL mysql_error(MYSQL *mysql) 02980 { 02981 return mysql->net.last_error; 02982 } 02983 02984 02985 /* 02986 Get version number for server in a form easy to test on 02987 02988 SYNOPSIS 02989 mysql_get_server_version() 02990 mysql Connection 02991 02992 EXAMPLE 02993 4.1.0-alfa -> 40100 02994 02995 NOTES 02996 We will ensure that a newer server always has a bigger number. 02997 02998 RETURN 02999 Signed number > 323000 03000 */ 03001 03002 ulong STDCALL 03003 mysql_get_server_version(MYSQL *mysql) 03004 { 03005 uint major, minor, version; 03006 char *pos= mysql->server_version, *end_pos; 03007 major= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1; 03008 minor= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1; 03009 version= (uint) strtoul(pos, &end_pos, 10); 03010 return (ulong) major*10000L+(ulong) (minor*100+version); 03011 } 03012 03013 03014 /* 03015 mysql_set_character_set function sends SET NAMES cs_name to 03016 the server (which changes character_set_client, character_set_result 03017 and character_set_connection) and updates mysql->charset so other 03018 functions like mysql_real_escape will work correctly. 03019 */ 03020 int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name) 03021 { 03022 struct charset_info_st *cs; 03023 const char *save_csdir= charsets_dir; 03024 03025 if (mysql->options.charset_dir) 03026 charsets_dir= mysql->options.charset_dir; 03027 03028 if (strlen(cs_name) < MY_CS_NAME_SIZE && 03029 (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0)))) 03030 { 03031 char buff[MY_CS_NAME_SIZE + 10]; 03032 charsets_dir= save_csdir; 03033 /* Skip execution of "SET NAMES" for pre-4.1 servers */ 03034 if (mysql_get_server_version(mysql) < 40100) 03035 return 0; 03036 sprintf(buff, "SET NAMES %s", cs_name); 03037 if (!mysql_real_query(mysql, buff, strlen(buff))) 03038 { 03039 mysql->charset= cs; 03040 } 03041 } 03042 else 03043 { 03044 char cs_dir_name[FN_REFLEN]; 03045 get_charsets_dir(cs_dir_name); 03046 mysql->net.last_errno= CR_CANT_READ_CHARSET; 03047 strmov(mysql->net.sqlstate, unknown_sqlstate); 03048 my_snprintf(mysql->net.last_error, sizeof(mysql->net.last_error) - 1, 03049 ER(mysql->net.last_errno), cs_name, cs_dir_name); 03050 03051 } 03052 charsets_dir= save_csdir; 03053 return mysql->net.last_errno; 03054 } 03055 03056
1.4.7

