diff options
author | unknown <hf@deer.mysql.r18.ru> | 2003-05-02 21:07:41 +0500 |
---|---|---|
committer | unknown <hf@deer.mysql.r18.ru> | 2003-05-02 21:07:41 +0500 |
commit | a1e47ce8ee3746a6ecf05d8c4707bea914fa14be (patch) | |
tree | fdde26b1e7037d8e84b46afae68af0c9adc79943 /sql/mini_client.cc | |
parent | 4a506d6e23845bf5d8208da741bd85cdcb0d4270 (diff) | |
download | mariadb-git-a1e47ce8ee3746a6ecf05d8c4707bea914fa14be.tar.gz |
SCRUM
common parts of libmysql.c and sql/mini_client.cc moved to sql-common/client.c
names of functions now are same in both cases
libmysql/libmysql.c:
many parts moved to sql-common/client.c
libmysqld/Makefile.am:
superfluous files removed
sql/mini_client.cc:
most of the file moved to sql-common/client.c
sql/mini_client.h:
mc_ prefixes were deleted
sql/repl_failsafe.cc:
mc_ prefixes removed
sql/slave.cc:
_mc prefixes removed
Diffstat (limited to 'sql/mini_client.cc')
-rw-r--r-- | sql/mini_client.cc | 1335 |
1 files changed, 6 insertions, 1329 deletions
diff --git a/sql/mini_client.cc b/sql/mini_client.cc index afcee5fbb02..8c431c0d1be 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -76,18 +76,6 @@ extern "C" { // Because of SCO 3.2V4.2 #endif } -static void mc_free_rows(MYSQL_DATA *cur); -void mc_end_server(MYSQL *mysql); -static int mc_sock_connect(File s, const struct sockaddr *name, uint namelen, uint to); -static void mc_free_old_query(MYSQL *mysql); -static int mc_send_file_to_server(MYSQL *mysql, const char *filename); -static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, - ulong *lengths); -static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - uint fields); - - - #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \ CLIENT_LOCAL_FILES | CLIENT_SECURE_CONNECTION) @@ -99,1324 +87,13 @@ static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, #define SOCKET_ERROR -1 #endif -#ifdef __WIN__ -static my_bool is_NT(void) -{ - char *os=getenv("OS"); - return (os && !strcmp(os, "Windows_NT")) ? 1 : 0; -} -#endif - extern ulong slave_net_timeout; +#define _mini_client_c +#define init_sigpipe_variables +#define set_sigpipe(mysql) +#define reset_sigpipe(mysql) +#include "../sql-common/client.c" -/* -** Create a named pipe connection -*/ - -#ifdef __WIN__ - -HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, - char **arg_unix_socket) -{ - HANDLE hPipe=INVALID_HANDLE_VALUE; - char szPipeName [ 257 ]; - DWORD dwMode; - int i; - my_bool testing_named_pipes=0; - char *host= *arg_host, *unix_socket= *arg_unix_socket; - - if (!host || !strcmp(host,LOCAL_HOST)) - host=LOCAL_HOST_NAMEDPIPE; - - sprintf(szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket); - DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s", - host, unix_socket)); - - for (i=0 ; i < 100 ; i++) /* Don't retry forever */ - { - if ((hPipe = CreateFile(szPipeName, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - 0, - NULL )) != INVALID_HANDLE_VALUE) - break; - if (GetLastError() != ERROR_PIPE_BUSY) - { - net->last_errno=CR_NAMEDPIPEOPEN_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - /* wait for for an other instance */ - if (! WaitNamedPipe(szPipeName, connect_timeout*1000) ) - { - net->last_errno=CR_NAMEDPIPEWAIT_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - } - if (hPipe == INVALID_HANDLE_VALUE) - { - net->last_errno=CR_NAMEDPIPEOPEN_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - dwMode = PIPE_READMODE_BYTE | PIPE_WAIT; - if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) ) - { - CloseHandle( hPipe ); - net->last_errno=CR_NAMEDPIPESETSTATE_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - *arg_host=host ; *arg_unix_socket=unix_socket; /* connect arg */ - return (hPipe); -} -#endif - - -/**************************************************************************** -** Init MySQL structure or allocate one -****************************************************************************/ - -MYSQL *mc_mysql_init(MYSQL *mysql) -{ - init_client_errs(); - if (!mysql) - { - if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL)))) - return 0; - mysql->free_me=1; - mysql->net.vio = 0; - } - else - bzero((char*) (mysql),sizeof(*(mysql))); -#ifdef __WIN__ - mysql->options.connect_timeout=20; -#endif - mysql->net.read_timeout = slave_net_timeout; - return mysql; -} - -/************************************************************************** -** Shut down connection -**************************************************************************/ - -void -mc_end_server(MYSQL *mysql) -{ - DBUG_ENTER("mc_end_server"); - if (mysql->net.vio != 0) - { - DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio))); - vio_delete(mysql->net.vio); - mysql->net.vio= 0; /* Marker */ - } - net_end(&mysql->net); - mc_free_old_query(mysql); - DBUG_VOID_RETURN; -} - -static void mc_free_old_query(MYSQL *mysql) -{ - DBUG_ENTER("mc_free_old_query"); - if (mysql->fields) - free_root(&mysql->field_alloc,MYF(0)); - else - init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */ - mysql->fields=0; - mysql->field_count=0; /* For API */ - DBUG_VOID_RETURN; -} - - -/**************************************************************************** -* A modified version of connect(). mc_sock_connect() allows you to specify -* a timeout value, in seconds, that we should wait until we -* derermine we can't connect to a particular host. If timeout is 0, -* mc_sock_connect() will behave exactly like connect(). -* -* Base version coded by Steve Bernacki, Jr. <steve@navinet.net> -*****************************************************************************/ - -static int mc_sock_connect(my_socket s, const struct sockaddr *name, - uint namelen, uint to) -{ -#if defined(__WIN__) || defined(OS2) - return connect(s, (struct sockaddr*) name, namelen); -#else - int flags, res, s_err; - SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint); - fd_set sfds; - struct timeval tv; - - /* If they passed us a timeout of zero, we should behave - * exactly like the normal connect() call does. - */ - - if (to == 0) - return connect(s, (struct sockaddr*) name, namelen); - - flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */ -#ifdef O_NONBLOCK - fcntl(s, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */ -#endif - - res = connect(s, (struct sockaddr*) name, namelen); - s_err = errno; /* Save the error... */ - fcntl(s, F_SETFL, flags); - if ((res != 0) && (s_err != EINPROGRESS)) - { - errno = s_err; /* Restore it */ - return(-1); - } - if (res == 0) /* Connected quickly! */ - return(0); - - /* Otherwise, our connection is "in progress." We can use - * the select() call to wait up to a specified period of time - * for the connection to suceed. If select() returns 0 - * (after waiting howevermany seconds), our socket never became - * writable (host is probably unreachable.) Otherwise, if - * select() returns 1, then one of two conditions exist: - * - * 1. An error occured. We use getsockopt() to check for this. - * 2. The connection was set up sucessfully: getsockopt() will - * return 0 as an error. - * - * Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk> - * who posted this method of timing out a connect() in - * comp.unix.programmer on August 15th, 1997. - */ - - FD_ZERO(&sfds); - FD_SET(s, &sfds); - tv.tv_sec = (long) to; - tv.tv_usec = 0; -#ifdef HPUX10 - res = select(s+1, NULL, (int*) &sfds, NULL, &tv); -#else - res = select(s+1, NULL, &sfds, NULL, &tv); -#endif /* HPUX10 */ - if (res <= 0) /* Never became writable */ - return(-1); - - /* select() returned something more interesting than zero, let's - * see if we have any errors. If the next two statements pass, - * we've got an open socket! - */ - - s_err=0; - if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) - return(-1); - - if (s_err) - { // getsockopt() could succeed - errno = s_err; - return(-1); // but return an error... - } - return(0); /* It's all good! */ -#endif -} - -/***************************************************************************** -** read a packet from server. Give error message if socket was down -** or packet is an error message -*****************************************************************************/ - -ulong -mc_net_safe_read(MYSQL *mysql) -{ - NET *net= &mysql->net; - ulong len=0; - - if (net->vio != 0) - len=my_net_read(net); - - if (len == packet_error || len == 0) - { - DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", - vio_description(net->vio),len)); - if (socket_errno != SOCKET_EINTR) - { - mc_end_server(mysql); - if (net->last_errno != ER_NET_PACKET_TOO_LARGE) - { - net->last_errno=CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - } - else - strmov(net->last_error, "Packet too large - increase \ -max_allowed_packet on this server"); - } - return(packet_error); - } - if (net->read_pos[0] == 255) - { - if (len > 3) - { - char *pos=(char*) net->read_pos+1; - if (mysql->protocol_version > 9) - { /* New client protocol */ - net->last_errno=uint2korr(pos); - pos+=2; - len-=2; - if (!net->last_errno) - net->last_errno = CR_UNKNOWN_ERROR; - } - else - { - net->last_errno=CR_UNKNOWN_ERROR; - len--; - } - (void) strmake(net->last_error,(char*) pos, - min(len,sizeof(net->last_error)-1)); - } - else - { - net->last_errno=CR_UNKNOWN_ERROR; - (void) strmov(net->last_error,ER(net->last_errno)); - } - DBUG_PRINT("error",("Got error: %d (%s)", net->last_errno, - net->last_error)); - return(packet_error); - } - return len; -} - - -char *mc_mysql_error(MYSQL *mysql) -{ - return (mysql)->net.last_error; -} - -int mc_mysql_errno(MYSQL *mysql) -{ - return (mysql)->net.last_errno; -} - - -my_bool mc_mysql_reconnect(MYSQL *mysql) -{ - MYSQL tmp_mysql; - DBUG_ENTER("mc_mysql_reconnect"); - - if (!mysql->reconnect) - { - mysql->net.last_errno=CR_SERVER_GONE_ERROR; - strmov(mysql->net.last_error, ER(mysql->net.last_errno)); - DBUG_RETURN(1); - } - mc_mysql_init(&tmp_mysql); - tmp_mysql.options=mysql->options; - if (!mc_mysql_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, - mysql->db, mysql->port, mysql->unix_socket, - mysql->client_flag, mysql->net.read_timeout)) - { - mysql->net.last_errno= tmp_mysql.net.last_errno; - strmov(mysql->net.last_error, tmp_mysql.net.last_error); - DBUG_RETURN(1); - } - tmp_mysql.free_me=mysql->free_me; - mysql->free_me=0; - bzero((char*) &mysql->options,sizeof(&mysql->options)); - mc_mysql_close(mysql); - *mysql=tmp_mysql; - net_clear(&mysql->net); - mysql->affected_rows= ~(my_ulonglong) 0; - DBUG_RETURN(0); -} - - - -int -mc_simple_command(MYSQL *mysql,enum enum_server_command command, - const char *arg, uint length, my_bool skipp_check) -{ - NET *net= &mysql->net; - int result= -1; - - if (mysql->net.vio == 0) - { /* Do reconnect if possible */ - if (mc_mysql_reconnect(mysql)) - goto end; - } - if (mysql->status != MYSQL_STATUS_READY) - { - strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); - goto end; - } - - mysql->net.last_error[0]=0; - mysql->net.last_errno=0; - mysql->net.report_error=0; - mysql->info=0; - mysql->affected_rows= ~(my_ulonglong) 0; - net_clear(net); /* Clear receive buffer */ - if (!arg) - arg=""; - - if (net_write_command(net, (uchar) command, NullS, 0, arg, length)) - { - DBUG_PRINT("error",("Can't send command to server. Error: %d", - socket_errno)); - mc_end_server(mysql); - if (mc_mysql_reconnect(mysql)) - goto end; - if (net_write_command(net,(uchar) command, NullS, 0, arg, length)) - { - net->last_errno=CR_SERVER_GONE_ERROR; - strmov(net->last_error,ER(net->last_errno)); - goto end; - } - } - result=0; - if (!skipp_check) - result= ((mysql->packet_length=mc_net_safe_read(mysql)) == packet_error ? - -1 : 0); - end: - return result; -} - - -MYSQL * -mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, - const char *passwd, const char *db, - uint port, const char *unix_socket,uint client_flag, - uint net_read_timeout) -{ - char buff[NAME_LEN+USERNAME_LENGTH+100],*end,*host_info; - char password_hash[SCRAMBLE41_LENGTH]; - my_socket sock; - ulong ip_addr; - struct sockaddr_in sock_addr; - ulong pkt_length; - NET *net= &mysql->net; - thr_alarm_t alarmed; - ALARM alarm_buff; - ulong max_allowed_packet; - -#ifdef __WIN__ - HANDLE hPipe=INVALID_HANDLE_VALUE; -#endif -#ifdef HAVE_SYS_UN_H - struct sockaddr_un UNIXaddr; -#endif - DBUG_ENTER("mc_mysql_connect"); - DBUG_PRINT("enter",("host: %s db: %s user: %s connect_time_out: %u read_timeout: %u", - host ? host : "(Null)", - db ? db : "(Null)", - user ? user : "(Null)", - net_read_timeout, - (uint) slave_net_timeout)); - net->vio = 0; /* If something goes wrong */ - mysql->charset=default_charset_info; /* Set character set */ - if (!port) - port = MYSQL_PORT; /* Should always be set by mysqld */ - if (!unix_socket) - unix_socket=MYSQL_UNIX_ADDR; - - mysql->reconnect=1; /* Reconnect as default */ - mysql->server_status=SERVER_STATUS_AUTOCOMMIT; - if (!mysql->options.connect_timeout) - mysql->options.connect_timeout= net_read_timeout; - - /* - ** Grab a socket and connect it to the server - */ - -#if defined(HAVE_SYS_UN_H) - if ((!host || !strcmp(host,LOCAL_HOST)) && unix_socket) - { - host=LOCAL_HOST; - host_info=(char*) ER(CR_LOCALHOST_CONNECTION); - DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); - if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) - { - net->last_errno=CR_SOCKET_CREATE_ERROR; - sprintf(net->last_error,ER(net->last_errno),socket_errno); - goto error; - } - net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); - bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); - UNIXaddr.sun_family = AF_UNIX; - strmov(UNIXaddr.sun_path, unix_socket); - if (mc_sock_connect(sock, - my_reinterpret_cast(struct sockaddr *) (&UNIXaddr), - sizeof(UNIXaddr), - mysql->options.connect_timeout) <0) - { - DBUG_PRINT("error",("Got error %d on connect to local server", - socket_errno)); - net->last_errno=CR_CONNECTION_ERROR; - sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno); - goto error; - } - } - else -#elif defined(__WIN__) - { - if ((unix_socket || - !host && is_NT() || - host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) || - mysql->options.named_pipe || !have_tcpip)) - { - sock=0; - if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, - (char**) &host, (char**) &unix_socket)) == - INVALID_HANDLE_VALUE) - { - DBUG_PRINT("error", - ("host: '%s' socket: '%s' named_pipe: %d have_tcpip: %d", - host ? host : "<null>", - unix_socket ? unix_socket : "<null>", - (int) mysql->options.named_pipe, - (int) have_tcpip)); - if (mysql->options.named_pipe || - (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || - (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE))) - goto error; /* User only requested named pipes */ - /* Try also with TCP/IP */ - } - else - { - net->vio=vio_new_win32pipe(hPipe); - sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host, - unix_socket); - } - } - } - if (hPipe == INVALID_HANDLE_VALUE) -#endif - { - unix_socket=0; /* This is not used */ - if (!host) - host=LOCAL_HOST; - sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); - DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); - thr_alarm_init(&alarmed); - thr_alarm(&alarmed, net_read_timeout, &alarm_buff); - sock = (my_socket) socket(AF_INET,SOCK_STREAM,0); - thr_end_alarm(&alarmed); - if (sock == SOCKET_ERROR) - { - net->last_errno=CR_IPSOCK_ERROR; - sprintf(net->last_error,ER(net->last_errno),socket_errno); - goto error; - } - net->vio = vio_new(sock,VIO_TYPE_TCPIP,FALSE); - bzero((char*) &sock_addr,sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - - /* - ** The server name may be a host name or IP address - */ - - if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) - { - memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); - } - else - { - int tmp_errno; - struct hostent tmp_hostent,*hp; - char buff2[GETHOSTBYNAME_BUFF_SIZE]; - hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2), - &tmp_errno); - if (!hp) - { - net->last_errno=CR_UNKNOWN_HOST; - sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno); - my_gethostbyname_r_free(); - goto error; - } - memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length); - my_gethostbyname_r_free(); - } - sock_addr.sin_port = (ushort) htons((ushort) port); - if (mc_sock_connect(sock, - my_reinterpret_cast(struct sockaddr *) (&sock_addr), - sizeof(sock_addr), - mysql->options.connect_timeout) <0) - { - DBUG_PRINT("error",("Got error %d on connect to '%s'", - socket_errno,host)); - net->last_errno= CR_CONN_HOST_ERROR; - sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, socket_errno); - goto error; - } - } - - if (!net->vio || my_net_init(net, net->vio)) - { - vio_delete(net->vio); - net->vio = 0; - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - vio_keepalive(net->vio,TRUE); - net->read_timeout=slave_net_timeout; - /* Get version info */ - mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ - if (mysql->options.connect_timeout && - vio_poll_read(net->vio, mysql->options.connect_timeout)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - if ((pkt_length=mc_net_safe_read(mysql)) == packet_error) - goto error; - - /* Check if version of protocol matches current one */ - - mysql->protocol_version= net->read_pos[0]; - DBUG_DUMP("packet",(char*) net->read_pos,10); - DBUG_PRINT("info",("mysql protocol version %d, server=%d", - PROTOCOL_VERSION, mysql->protocol_version)); - if (mysql->protocol_version != PROTOCOL_VERSION && - mysql->protocol_version != PROTOCOL_VERSION-1) - { - net->last_errno= CR_VERSION_ERROR; - sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version, - PROTOCOL_VERSION); - goto error; - } - end=strend((char*) net->read_pos+1); - mysql->thread_id=uint4korr(end+1); - end+=5; - strmake(mysql->scramble_buff,end,8); - end+=9; - if (pkt_length >= (uint) (end+1 - (char*) net->read_pos)) - mysql->server_capabilities=uint2korr(end); - if (pkt_length >= (uint) (end+18 - (char*) net->read_pos)) - { - /* New protocol with 16 bytes to describe server characteristics */ - mysql->server_language=end[2]; - mysql->server_status=uint2korr(end+3); - } - - /* Save connection information */ - if (!user) user=""; - if (!passwd) passwd=""; - if (!my_multi_malloc(MYF(0), - &mysql->host_info, (uint) strlen(host_info)+1, - &mysql->host, (uint) strlen(host)+1, - &mysql->unix_socket, - unix_socket ? (uint) strlen(unix_socket)+1 : (uint) 1, - &mysql->server_version, - (uint) (end - (char*) net->read_pos), - NullS) || - !(mysql->user=my_strdup(user,MYF(0))) || - !(mysql->passwd=my_strdup(passwd,MYF(0)))) - { - strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); - goto error; - } - strmov(mysql->host_info,host_info); - strmov(mysql->host,host); - if (unix_socket) - strmov(mysql->unix_socket,unix_socket); - else - mysql->unix_socket=0; - strmov(mysql->server_version,(char*) net->read_pos+1); - mysql->port=port; - client_flag|=mysql->options.client_flag; - DBUG_PRINT("info",("Server version = '%s' capabilites: %ld", - mysql->server_version,mysql->server_capabilities)); - - /* Send client information for access check */ - client_flag|=CLIENT_CAPABILITIES; - -#ifdef HAVE_OPENSSL - if (mysql->options.ssl_key || mysql->options.ssl_cert || - mysql->options.ssl_ca || mysql->options.ssl_capath || - mysql->options.ssl_cipher) - mysql->options.use_ssl= 1; - if (mysql->options.use_ssl) - client_flag|=CLIENT_SSL; -#endif /* HAVE_OPENSSL */ - - if (db) - client_flag|=CLIENT_CONNECT_WITH_DB; -#ifdef HAVE_COMPRESS - if ((mysql->server_capabilities & CLIENT_COMPRESS) && - (mysql->options.compress || (client_flag & CLIENT_COMPRESS))) - client_flag|=CLIENT_COMPRESS; /* We will use compression */ - else -#endif - client_flag&= ~CLIENT_COMPRESS; - -#ifdef HAVE_OPENSSL - if ((mysql->server_capabilities & CLIENT_SSL) && - (mysql->options.use_ssl || (client_flag & CLIENT_SSL))) - { - DBUG_PRINT("info", ("Changing IO layer to SSL")); - client_flag |= CLIENT_SSL; - } - else - { - if (client_flag & CLIENT_SSL) - { - DBUG_PRINT("info", ("Leaving IO layer intact because server doesn't support SSL")); - } - client_flag &= ~CLIENT_SSL; - } -#endif /* HAVE_OPENSSL */ - - int2store(buff,client_flag); - mysql->client_flag=client_flag; - -#ifdef HAVE_OPENSSL - /* - Oops.. are we careful enough to not send ANY information without - encryption? - */ - if (client_flag & CLIENT_SSL) - { - if (my_net_write(net,buff,(uint) (2)) || net_flush(net)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - /* Do the SSL layering. */ - DBUG_PRINT("info", ("IO layer change in progress...")); - DBUG_PRINT("info", ("IO context %p",((struct st_VioSSLConnectorFd*)mysql->connector_fd)->ssl_context_)); - sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),mysql->net.vio, (long)(mysql->options.connect_timeout)); - DBUG_PRINT("info", ("IO layer change done!")); - } -#endif /* HAVE_OPENSSL */ - max_allowed_packet=mysql->net.max_packet_size; - int3store(buff+2,max_allowed_packet); - - - if (user && user[0]) - strmake(buff+5,user,32); - else - { - user = getenv("USER"); - if (!user) user = "mysql"; - strmov((char*) buff+5, user ); - } - - DBUG_PRINT("info",("user: %s",buff+5)); - - /* - We always start with old type handshake the only difference is message sent - If server handles secure connection type we'll not send the real scramble - */ - if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) - { - if (passwd[0]) - { - /* Prepare false scramble */ - end=strend(buff+5)+1; - bfill(end, SCRAMBLE_LENGTH, 'x'); - end+=SCRAMBLE_LENGTH; - *end=0; - } - else /* For empty password*/ - { - end=strend(buff+5)+1; - *end=0; /* Store zero length scramble */ - } - } - else - { - /* - Real scramble is only sent to old servers. This can be blocked - by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); - */ - end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd, - (my_bool) (mysql->protocol_version == 9)); - - } - /* Add database if needed */ - if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) - { - end=strmake(end+1,db,NAME_LEN); - mysql->db=my_strdup(db,MYF(MY_WME)); - db=0; - } - /* Write authentication package */ - if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - - /* We shall only query sever if it expect us to do so */ - - if ( (pkt_length=mc_net_safe_read(mysql)) == packet_error) - goto error; - - if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) - { - /* This should always happen with new server unless empty password */ - if (pkt_length==24 && net->read_pos[0]) - /* OK/Error message has zero as the first character */ - { - /* Old passwords will have zero at the first byte of hash */ - if (net->read_pos[0] != '*') - { - /* Build full password hash as it is required to decode scramble */ - password_hash_stage1(buff, passwd); - /* Store copy as we'll need it later */ - memcpy(password_hash,buff,SCRAMBLE41_LENGTH); - /* Finally hash complete password using hash we got from server */ - password_hash_stage2(password_hash,(char*)net->read_pos); - /* Decypt and store scramble 4 = hash for stage2 */ - password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash, - SCRAMBLE41_LENGTH); - mysql->scramble_buff[SCRAMBLE41_LENGTH]=0; - /* Encode scramble with password. Recycle buffer */ - password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH); - } - else - { - /* Create password to decode scramble */ - create_key_from_old_password(passwd,password_hash); - /* Decypt and store scramble 4 = hash for stage2 */ - password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash, - SCRAMBLE41_LENGTH); - mysql->scramble_buff[SCRAMBLE41_LENGTH]=0; - /* Finally scramble decoded scramble with password */ - scramble(buff, mysql->scramble_buff, passwd,0); - } - /* Write second package of authentication */ - if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - /* Read What server thinks about out new auth message report */ - if (mc_net_safe_read(mysql) == packet_error) - goto error; - } - } - - /* End of authentication part of handshake */ - - if (client_flag & CLIENT_COMPRESS) /* We will use compression */ - net->compress=1; - DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); - DBUG_RETURN(mysql); - -error: - DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error)); - { - /* Free alloced memory */ - my_bool free_me=mysql->free_me; - mc_end_server(mysql); - mysql->free_me=0; - mc_mysql_close(mysql); - mysql->free_me=free_me; - } - DBUG_RETURN(0); -} - - -#ifdef HAVE_OPENSSL -/* -************************************************************************** -** Free strings in the SSL structure and clear 'use_ssl' flag. -** NB! Errors are not reported until you do mysql_real_connect. -************************************************************************** -*/ -int -mysql_ssl_clear(MYSQL *mysql) -{ - my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); - mysql->options.ssl_key = 0; - mysql->options.ssl_cert = 0; - mysql->options.ssl_ca = 0; - mysql->options.ssl_capath = 0; - mysql->options.ssl_cipher= 0; - mysql->options.use_ssl = FALSE; - my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); - mysql->connector_fd = 0; - return 0; -} -#endif /* HAVE_OPENSSL */ - -/************************************************************************* -** Send a QUIT to the server and close the connection -** If handle is alloced by mysql connect free it. -*************************************************************************/ - -void -mc_mysql_close(MYSQL *mysql) -{ - DBUG_ENTER("mysql_close"); - if (mysql) /* Some simple safety */ - { - if (mysql->net.vio != 0) - { - mc_free_old_query(mysql); - mysql->status=MYSQL_STATUS_READY; /* Force command */ - mysql->reconnect=0; - mc_simple_command(mysql,COM_QUIT,NullS,0,1); - mc_end_server(mysql); - } - my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); - /* Clear pointers for better safety */ - mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; - bzero((char*) &mysql->options,sizeof(mysql->options)); -#ifdef HAVE_OPENSSL - mysql_ssl_clear(mysql); -#endif /* HAVE_OPENSSL */ - if (mysql->free_me) - my_free((gptr) mysql,MYF(0)); - } - DBUG_VOID_RETURN; -} - -void mc_mysql_free_result(MYSQL_RES *result) -{ - DBUG_ENTER("mc_mysql_free_result"); - DBUG_PRINT("enter",("mysql_res: %lx",result)); - if (result) - { - if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT) - { - DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows")); - for (;;) - { - ulong pkt_len; - if ((pkt_len=mc_net_safe_read(result->handle)) == packet_error) - break; - if (pkt_len == 1 && result->handle->net.read_pos[0] == 254) - break; /* End of data */ - } - result->handle->status=MYSQL_STATUS_READY; - } - mc_free_rows(result->data); - if (result->fields) - free_root(&result->field_alloc,MYF(0)); - if (result->row) - my_free((gptr) result->row,MYF(0)); - my_free((gptr) result,MYF(0)); - } - DBUG_VOID_RETURN; -} - -static void mc_free_rows(MYSQL_DATA *cur) -{ - if (cur) - { - free_root(&cur->alloc,MYF(0)); - my_free((gptr) cur,MYF(0)); - } -} - -static MYSQL_FIELD * -mc_unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, - my_bool default_value, my_bool long_flag_protocol) -{ - MYSQL_ROWS *row; - MYSQL_FIELD *field,*result; - DBUG_ENTER("unpack_fields"); - - field=result=(MYSQL_FIELD*) alloc_root(alloc,sizeof(MYSQL_FIELD)*fields); - if (!result) - DBUG_RETURN(0); - - for (row=data->data; row ; row = row->next,field++) - { - field->table= strdup_root(alloc,(char*) row->data[0]); - field->name= strdup_root(alloc,(char*) row->data[1]); - field->length= (uint) uint3korr(row->data[2]); - field->type= (enum enum_field_types) (uchar) row->data[3][0]; - if (long_flag_protocol) - { - field->flags= uint2korr(row->data[4]); - field->decimals=(uint) (uchar) row->data[4][2]; - } - else - { - field->flags= (uint) (uchar) row->data[4][0]; - field->decimals=(uint) (uchar) row->data[4][1]; - } - if (INTERNAL_NUM_FIELD(field)) - field->flags|= NUM_FLAG; - if (default_value && row->data[5]) - field->def=strdup_root(alloc,(char*) row->data[5]); - else - field->def=0; - field->max_length= 0; - } - mc_free_rows(data); /* Free old data */ - DBUG_RETURN(result); -} - -int mc_mysql_send_query(MYSQL* mysql, const char* query, uint length) -{ - return mc_simple_command(mysql, COM_QUERY, query, length, 1); -} - - -int mc_mysql_read_query_result(MYSQL *mysql) -{ - uchar *pos; - ulong field_count; - MYSQL_DATA *fields; - ulong length; - DBUG_ENTER("mc_mysql_read_query_result"); - - if ((length = mc_net_safe_read(mysql)) == packet_error) - DBUG_RETURN(-1); - mc_free_old_query(mysql); /* Free old result */ -get_info: - pos=(uchar*) mysql->net.read_pos; - if ((field_count= net_field_length(&pos)) == 0) - { - mysql->affected_rows= net_field_length_ll(&pos); - mysql->insert_id= net_field_length_ll(&pos); - if (mysql->server_capabilities & CLIENT_TRANSACTIONS) - { - mysql->server_status=uint2korr(pos); pos+=2; - } - if (pos < mysql->net.read_pos+length && net_field_length(&pos)) - mysql->info=(char*) pos; - DBUG_RETURN(0); - } - if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */ - { - int error=mc_send_file_to_server(mysql,(char*) pos); - if ((length=mc_net_safe_read(mysql)) == packet_error || error) - DBUG_RETURN(-1); - goto get_info; /* Get info packet */ - } - if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) - mysql->server_status|= SERVER_STATUS_IN_TRANS; - - mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */ - if (!(fields=mc_read_rows(mysql,(MYSQL_FIELD*) 0,5))) - DBUG_RETURN(-1); - if (!(mysql->fields=mc_unpack_fields(fields,&mysql->field_alloc, - (uint) field_count,0, - (my_bool) test(mysql->server_capabilities & - CLIENT_LONG_FLAG)))) - DBUG_RETURN(-1); - mysql->status=MYSQL_STATUS_GET_RESULT; - mysql->field_count=field_count; - DBUG_RETURN(0); -} - - -int mc_mysql_query(MYSQL *mysql, const char *query, uint length) -{ - DBUG_ENTER("mc_mysql_query"); - DBUG_PRINT("enter",("handle: %lx",mysql)); - DBUG_PRINT("query",("Query = \"%s\"",query)); - DBUG_ASSERT(length == strlen(query)); - if (mc_simple_command(mysql,COM_QUERY,query,length,1)) - DBUG_RETURN(-1); - DBUG_RETURN(mc_mysql_read_query_result(mysql)); -} - - -static int mc_send_file_to_server(MYSQL *mysql, const char *filename) -{ - int fd, readcount, result= -1; - uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE); - char *buf, tmp_name[FN_REFLEN]; - DBUG_ENTER("send_file_to_server"); - - if (!(buf=my_malloc(packet_length,MYF(0)))) - { - strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY)); - DBUG_RETURN(-1); - } - - fn_format(tmp_name,filename,"","",4); /* Convert to client format */ - if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0) - { - my_net_write(&mysql->net,"",0); // Server needs one packet - net_flush(&mysql->net); - mysql->net.last_errno=EE_FILENOTFOUND; - my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, - EE(mysql->net.last_errno),tmp_name, errno); - goto err; - } - - while ((readcount = (int) my_read(fd,(byte*) buf,packet_length,MYF(0))) > 0) - { - if (my_net_write(&mysql->net,buf,readcount)) - { - DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file")); - mysql->net.last_errno=CR_SERVER_LOST; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); - goto err; - } - } - /* Send empty packet to mark end of file */ - if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net)) - { - mysql->net.last_errno=CR_SERVER_LOST; - sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno); - goto err; - } - if (readcount < 0) - { - mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */ - my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, - tmp_name,errno); - goto err; - } - result=0; // Ok - -err: - if (fd >= 0) - (void) my_close(fd,MYF(0)); - my_free(buf,MYF(0)); - DBUG_RETURN(result); -} - -/* Read all rows (fields or data) from server */ - -static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - uint fields) -{ - uint field; - ulong pkt_len; - ulong len; - uchar *cp; - char *to; - MYSQL_DATA *result; - MYSQL_ROWS **prev_ptr,*cur; - NET *net = &mysql->net; - DBUG_ENTER("mc_read_rows"); - - if ((pkt_len=mc_net_safe_read(mysql)) == packet_error) - DBUG_RETURN(0); - if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), - MYF(MY_ZEROFILL)))) - { - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); - DBUG_RETURN(0); - } - init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */ - result->alloc.min_malloc=sizeof(MYSQL_ROWS); - prev_ptr= &result->data; - result->rows=0; - result->fields=fields; - - while (*(cp=net->read_pos) != 254 || pkt_len != 1) - { - result->rows++; - if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc, - sizeof(MYSQL_ROWS))) || - !(cur->data= ((MYSQL_ROW) - alloc_root(&result->alloc, - (fields+1)*sizeof(char *)+pkt_len)))) - { - mc_free_rows(result); - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); - DBUG_RETURN(0); - } - *prev_ptr=cur; - prev_ptr= &cur->next; - to= (char*) (cur->data+fields+1); - for (field=0 ; field < fields ; field++) - { - if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH) - { /* null field */ - cur->data[field] = 0; - } - else - { - cur->data[field] = to; - memcpy(to,(char*) cp,len); to[len]=0; - to+=len+1; - cp+=len; - if (mysql_fields) - { - if (mysql_fields[field].max_length < len) - mysql_fields[field].max_length=len; - } - } - } - cur->data[field]=to; /* End of last field */ - if ((pkt_len=mc_net_safe_read(mysql)) == packet_error) - { - mc_free_rows(result); - DBUG_RETURN(0); - } - } - *prev_ptr=0; /* last pointer is null */ - DBUG_PRINT("exit",("Got %d rows",result->rows)); - DBUG_RETURN(result); -} - - -/* -** Read one row. Uses packet buffer as storage for fields. -** When next packet is read, the previous field values are destroyed -*/ - - -static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, - ulong *lengths) -{ - uint field; - ulong pkt_len,len; - uchar *pos; - uchar *prev_pos; - - if ((pkt_len=mc_net_safe_read(mysql)) == packet_error) - return -1; - if (pkt_len == 1 && mysql->net.read_pos[0] == 254) - return 1; /* End of data */ - prev_pos= 0; /* allowed to write at packet[-1] */ - pos=mysql->net.read_pos; - for (field=0 ; field < fields ; field++) - { - if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH) - { /* null field */ - row[field] = 0; - *lengths++=0; - } - else - { - row[field] = (char*) pos; - pos+=len; - *lengths++=len; - } - if (prev_pos) - *prev_pos=0; /* Terminate prev field */ - prev_pos= pos; - } - row[field]=(char*) prev_pos+1; /* End of last field */ - *prev_pos=0; /* Terminate last field */ - return 0; -} - -my_ulonglong mc_mysql_num_rows(MYSQL_RES *res) -{ - return res->row_count; -} - -unsigned int mc_mysql_num_fields(MYSQL_RES *res) -{ - return res->field_count; -} - -void mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row) -{ - MYSQL_ROWS *tmp=0; - DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row)); - if (result->data) - for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ; - result->current_row=0; - result->data_cursor = tmp; -} - -MYSQL_ROW STDCALL mc_mysql_fetch_row(MYSQL_RES *res) -{ - DBUG_ENTER("mc_mysql_fetch_row"); - if (!res->data) - { /* Unbufferred fetch */ - if (!res->eof) - { - if (!(mc_read_one_row(res->handle,res->field_count,res->row, - res->lengths))) - { - res->row_count++; - DBUG_RETURN(res->current_row=res->row); - } - else - { - DBUG_PRINT("info",("end of data")); - res->eof=1; - res->handle->status=MYSQL_STATUS_READY; - } - } - DBUG_RETURN((MYSQL_ROW) NULL); - } - { - MYSQL_ROW tmp; - if (!res->data_cursor) - { - DBUG_PRINT("info",("end of data")); - DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL); - } - tmp = res->data_cursor->data; - res->data_cursor = res->data_cursor->next; - DBUG_RETURN(res->current_row=tmp); - } -} - -int mc_mysql_select_db(MYSQL *mysql, const char *db) -{ - int error; - DBUG_ENTER("mysql_select_db"); - DBUG_PRINT("enter",("db: '%s'",db)); - - if ((error=mc_simple_command(mysql,COM_INIT_DB,db,(uint) strlen(db),0))) - DBUG_RETURN(error); - my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); - mysql->db=my_strdup(db,MYF(MY_WME)); - DBUG_RETURN(0); -} - +#endif /* HAVE_EXTERNAL_CLIENT */ -MYSQL_RES *mc_mysql_store_result(MYSQL *mysql) -{ - MYSQL_RES *result; - DBUG_ENTER("mysql_store_result"); - if (!mysql->fields) - DBUG_RETURN(0); - if (mysql->status != MYSQL_STATUS_GET_RESULT) - { - strmov(mysql->net.last_error, - ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); - DBUG_RETURN(0); - } - mysql->status=MYSQL_STATUS_READY; /* server is ready */ - if (!(result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+ - sizeof(ulong)*mysql->field_count, - MYF(MY_ZEROFILL)))) - { - mysql->net.last_errno=CR_OUT_OF_MEMORY; - strmov(mysql->net.last_error, ER(mysql->net.last_errno)); - DBUG_RETURN(0); - } - result->eof=1; /* Marker for buffered */ - result->lengths=(ulong*) (result+1); - if (!(result->data=mc_read_rows(mysql,mysql->fields,mysql->field_count))) - { - my_free((gptr) result,MYF(0)); - DBUG_RETURN(0); - } - mysql->affected_rows= result->row_count= result->data->rows; - result->data_cursor= result->data->data; - result->fields= mysql->fields; - result->field_alloc= mysql->field_alloc; - result->field_count= mysql->field_count; - result->current_field=0; - result->current_row=0; /* Must do a fetch first */ - mysql->fields=0; /* fields is now in result */ - DBUG_RETURN(result); /* Data fetched */ -} - -#endif /* HAVE_EXTERNAL_CLIENT */ |