root/ext/mysqlnd/mysqlnd_loaddata.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mysqlnd_local_infile_init
  2. mysqlnd_local_infile_read
  3. mysqlnd_local_infile_error
  4. mysqlnd_local_infile_end
  5. mysqlnd_local_infile_default
  6. mysqlnd_handle_local_infile

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 7                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 2006-2016 The PHP Group                                |
   6   +----------------------------------------------------------------------+
   7   | This source file is subject to version 3.01 of the PHP license,      |
   8   | that is bundled with this package in the file LICENSE, and is        |
   9   | available through the world-wide-web at the following url:           |
  10   | http://www.php.net/license/3_01.txt                                  |
  11   | If you did not receive a copy of the PHP license and are unable to   |
  12   | obtain it through the world-wide-web, please send a note to          |
  13   | license@php.net so we can mail you a copy immediately.               |
  14   +----------------------------------------------------------------------+
  15   | Authors: Andrey Hristov <andrey@mysql.com>                           |
  16   |          Ulf Wendel <uwendel@mysql.com>                              |
  17   |          Georg Richter <georg@mysql.com>                             |
  18   +----------------------------------------------------------------------+
  19 */
  20 
  21 #include "php.h"
  22 #include "php_globals.h"
  23 #include "mysqlnd.h"
  24 #include "mysqlnd_wireprotocol.h"
  25 #include "mysqlnd_priv.h"
  26 #include "mysqlnd_debug.h"
  27 
  28 /* {{{ mysqlnd_local_infile_init */
  29 static
  30 int mysqlnd_local_infile_init(void ** ptr, const char * const filename)
  31 {
  32         MYSQLND_INFILE_INFO     *info;
  33         php_stream_context      *context = NULL;
  34 
  35         DBG_ENTER("mysqlnd_local_infile_init");
  36 
  37         info = ((MYSQLND_INFILE_INFO *)mnd_ecalloc(1, sizeof(MYSQLND_INFILE_INFO)));
  38         if (!info) {
  39                 DBG_RETURN(1);
  40         }
  41 
  42         *ptr = info;
  43 
  44         /* check open_basedir */
  45         if (PG(open_basedir)) {
  46                 if (php_check_open_basedir_ex(filename, 0) == -1) {
  47                         strcpy(info->error_msg, "open_basedir restriction in effect. Unable to open file");
  48                         info->error_no = CR_UNKNOWN_ERROR;
  49                         DBG_RETURN(1);
  50                 }
  51         }
  52 
  53         info->filename = filename;
  54         info->fd = php_stream_open_wrapper_ex((char *)filename, "r", 0, NULL, context);
  55 
  56         if (info->fd == NULL) {
  57                 snprintf((char *)info->error_msg, sizeof(info->error_msg), "Can't find file '%-.64s'.", filename);
  58                 info->error_no = MYSQLND_EE_FILENOTFOUND;
  59                 DBG_RETURN(1);
  60         }
  61 
  62         DBG_RETURN(0);
  63 }
  64 /* }}} */
  65 
  66 
  67 /* {{{ mysqlnd_local_infile_read */
  68 static
  69 int mysqlnd_local_infile_read(void * ptr, zend_uchar * buf, unsigned int buf_len)
  70 {
  71         MYSQLND_INFILE_INFO     *info = (MYSQLND_INFILE_INFO *)ptr;
  72         int count;
  73 
  74         DBG_ENTER("mysqlnd_local_infile_read");
  75 
  76         count = (int) php_stream_read(info->fd, (char *) buf, buf_len);
  77 
  78         if (count < 0) {
  79                 strcpy(info->error_msg, "Error reading file");
  80                 info->error_no = CR_UNKNOWN_ERROR;
  81         }
  82 
  83         DBG_RETURN(count);
  84 }
  85 /* }}} */
  86 
  87 
  88 /* {{{ mysqlnd_local_infile_error */
  89 static
  90 int     mysqlnd_local_infile_error(void * ptr, char *error_buf, unsigned int error_buf_len)
  91 {
  92         MYSQLND_INFILE_INFO     *info = (MYSQLND_INFILE_INFO *)ptr;
  93 
  94         DBG_ENTER("mysqlnd_local_infile_error");
  95 
  96         if (info) {
  97                 strlcpy(error_buf, info->error_msg, error_buf_len);
  98                 DBG_INF_FMT("have info, %d", info->error_no);
  99                 DBG_RETURN(info->error_no);
 100         }
 101 
 102         strlcpy(error_buf, "Unknown error", error_buf_len);
 103         DBG_INF_FMT("no info, %d", CR_UNKNOWN_ERROR);
 104         DBG_RETURN(CR_UNKNOWN_ERROR);
 105 }
 106 /* }}} */
 107 
 108 
 109 /* {{{ mysqlnd_local_infile_end */
 110 static
 111 void mysqlnd_local_infile_end(void * ptr)
 112 {
 113         MYSQLND_INFILE_INFO     *info = (MYSQLND_INFILE_INFO *)ptr;
 114 
 115         if (info) {
 116                 /* php_stream_close segfaults on NULL */
 117                 if (info->fd) {
 118                         php_stream_close(info->fd);
 119                         info->fd = NULL;
 120                 }
 121                 mnd_efree(info);
 122         }
 123 }
 124 /* }}} */
 125 
 126 
 127 /* {{{ mysqlnd_local_infile_default */
 128 void
 129 mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn)
 130 {
 131         conn->infile.local_infile_init = mysqlnd_local_infile_init;
 132         conn->infile.local_infile_read = mysqlnd_local_infile_read;
 133         conn->infile.local_infile_error = mysqlnd_local_infile_error;
 134         conn->infile.local_infile_end = mysqlnd_local_infile_end;
 135 }
 136 /* }}} */
 137 
 138 
 139 static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of local file";
 140 
 141 
 142 /* {{{ mysqlnd_handle_local_infile */
 143 enum_func_status
 144 mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning)
 145 {
 146         zend_uchar                      *buf = NULL;
 147         zend_uchar                      empty_packet[MYSQLND_HEADER_SIZE];
 148         enum_func_status        result = FAIL;
 149         unsigned int            buflen = 4096;
 150         void                            *info = NULL;
 151         int                                     bufsize;
 152         size_t                          ret;
 153         MYSQLND_INFILE          infile;
 154         MYSQLND_NET                     * net = conn->net;
 155 
 156         DBG_ENTER("mysqlnd_handle_local_infile");
 157 
 158         if (!(conn->options->flags & CLIENT_LOCAL_FILES)) {
 159                 php_error_docref(NULL, E_WARNING, "LOAD DATA LOCAL INFILE forbidden");
 160                 /* write empty packet to server */
 161                 ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info);
 162                 *is_warning = TRUE;
 163                 goto infile_error;
 164         }
 165 
 166         infile = conn->infile;
 167         /* allocate buffer for reading data */
 168         buf = (zend_uchar *) mnd_ecalloc(1, buflen);
 169 
 170         *is_warning = FALSE;
 171 
 172         /* init handler: allocate read buffer and open file */
 173         if (infile.local_infile_init(&info, (char *)filename)) {
 174                 char tmp_buf[sizeof(conn->error_info->error)];
 175                 int tmp_error_no;
 176                 *is_warning = TRUE;
 177                 /* error occurred */
 178                 tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
 179                 SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
 180                 /* write empty packet to server */
 181                 ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info);
 182                 goto infile_error;
 183         }
 184 
 185         /* read data */
 186         while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE, buflen - MYSQLND_HEADER_SIZE)) > 0) {
 187                 if ((ret = net->data->m.send_ex(net, buf, bufsize, conn->stats, conn->error_info)) == 0) {
 188                         DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
 189                         SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
 190                         goto infile_error;
 191                 }
 192         }
 193 
 194         /* send empty packet for eof */
 195         if ((ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info)) == 0) {
 196                 SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
 197                 goto infile_error;
 198         }
 199 
 200         /* error during read occurred */
 201         if (bufsize < 0) {
 202                 char tmp_buf[sizeof(conn->error_info->error)];
 203                 int tmp_error_no;
 204                 *is_warning = TRUE;
 205                 DBG_ERR_FMT("Bufsize < 0, warning,  %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
 206                 tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
 207                 SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
 208                 goto infile_error;
 209         }
 210 
 211         result = PASS;
 212 
 213 infile_error:
 214         /* get response from server and update upsert values */
 215         if (FAIL == conn->m->simple_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_QUERY, FALSE)) {
 216                 result = FAIL;
 217         }
 218 
 219         (*conn->infile.local_infile_end)(info);
 220         if (buf) {
 221                 mnd_efree(buf);
 222         }
 223         DBG_INF_FMT("%s", result == PASS? "PASS":"FAIL");
 224         DBG_RETURN(result);
 225 }
 226 /* }}} */
 227 
 228 /*
 229  * Local variables:
 230  * tab-width: 4
 231  * c-basic-offset: 4
 232  * End:
 233  * vim600: noet sw=4 ts=4 fdm=marker
 234  * vim<600: noet sw=4 ts=4
 235  */

/* [<][>][^][v][top][bottom][index][help] */