Annotation of embedaddon/php/ext/mysqlnd/mysqlnd_loaddata.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:   +----------------------------------------------------------------------+
                      3:   | PHP Version 5                                                        |
                      4:   +----------------------------------------------------------------------+
1.1.1.4 ! misho       5:   | Copyright (c) 2006-2014 The PHP Group                                |
1.1       misho       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:   +----------------------------------------------------------------------+
1.1.1.2   misho      15:   | Authors: Andrey Hristov <andrey@mysql.com>                           |
1.1       misho      16:   |          Ulf Wendel <uwendel@mysql.com>                              |
1.1.1.2   misho      17:   |          Georg Richter <georg@mysql.com>                             |
1.1       misho      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
1.1.1.2   misho      30: int mysqlnd_local_infile_init(void ** ptr, char * filename, void ** userdata TSRMLS_DC)
1.1       misho      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 TSRMLS_CC) == -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
1.1.1.2   misho      69: int mysqlnd_local_infile_read(void * ptr, zend_uchar * buf, unsigned int buf_len TSRMLS_DC)
1.1       misho      70: {
                     71:        MYSQLND_INFILE_INFO     *info = (MYSQLND_INFILE_INFO *)ptr;
                     72:        int count;
                     73: 
                     74:        DBG_ENTER("mysqlnd_local_infile_read");
                     75: 
1.1.1.2   misho      76:        count = (int)php_stream_read(info->fd, (char *) buf, buf_len);
1.1       misho      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
1.1.1.2   misho      90: int    mysqlnd_local_infile_error(void * ptr, char *error_buf, unsigned int error_buf_len TSRMLS_DC)
1.1       misho      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
1.1.1.2   misho     111: void mysqlnd_local_infile_end(void * ptr TSRMLS_DC)
1.1       misho     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 */
1.1.1.2   misho     128: PHPAPI void
                    129: mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn)
1.1       misho     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: 
1.1.1.2   misho     138: 
1.1       misho     139: /* {{{ mysqlnd_set_local_infile_handler */
1.1.1.2   misho     140: PHPAPI void
                    141: mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, const char * const funcname)
1.1       misho     142: {
                    143:        if (!conn->infile.callback) {
                    144:                MAKE_STD_ZVAL(conn->infile.callback);
                    145:        } else {
                    146:                zval_dtor(conn->infile.callback);
                    147:        }
                    148:        ZVAL_STRING(conn->infile.callback, (char*) funcname, 1);
                    149: }
                    150: /* }}} */
                    151: 
                    152: 
                    153: static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of local file";
                    154: 
                    155: 
                    156: /* {{{ mysqlnd_handle_local_infile */
                    157: enum_func_status
1.1.1.2   misho     158: mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning TSRMLS_DC)
1.1       misho     159: {
1.1.1.2   misho     160:        zend_uchar                      *buf = NULL;
                    161:        zend_uchar                      empty_packet[MYSQLND_HEADER_SIZE];
1.1       misho     162:        enum_func_status        result = FAIL;
                    163:        unsigned int            buflen = 4096;
                    164:        void                            *info = NULL;
                    165:        int                                     bufsize;
                    166:        size_t                          ret;
                    167:        MYSQLND_INFILE          infile;
1.1.1.2   misho     168:        MYSQLND_NET                     * net = conn->net;
1.1       misho     169: 
                    170:        DBG_ENTER("mysqlnd_handle_local_infile");
                    171: 
1.1.1.2   misho     172:        if (!(conn->options->flags & CLIENT_LOCAL_FILES)) {
1.1       misho     173:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "LOAD DATA LOCAL INFILE forbidden");
                    174:                /* write empty packet to server */
1.1.1.2   misho     175:                ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC);
1.1       misho     176:                *is_warning = TRUE;
                    177:                goto infile_error;
                    178:        }
                    179: 
                    180:        infile = conn->infile;
                    181:        /* allocate buffer for reading data */
1.1.1.2   misho     182:        buf = (zend_uchar *) mnd_ecalloc(1, buflen);
1.1       misho     183: 
                    184:        *is_warning = FALSE;
                    185: 
                    186:        /* init handler: allocate read buffer and open file */
                    187:        if (infile.local_infile_init(&info, (char *)filename, conn->infile.userdata TSRMLS_CC)) {
1.1.1.2   misho     188:                char tmp_buf[sizeof(conn->error_info->error)];
                    189:                int tmp_error_no;
1.1       misho     190:                *is_warning = TRUE;
1.1.1.3   misho     191:                /* error occurred */
1.1.1.2   misho     192:                tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf) TSRMLS_CC);
                    193:                SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
1.1       misho     194:                /* write empty packet to server */
1.1.1.2   misho     195:                ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC);
1.1       misho     196:                goto infile_error;
                    197:        }
                    198: 
                    199:        /* read data */
                    200:        while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE, buflen - MYSQLND_HEADER_SIZE TSRMLS_CC)) > 0) {
1.1.1.2   misho     201:                if ((ret = net->m.send_ex(net, buf, bufsize, conn->stats, conn->error_info TSRMLS_CC)) == 0) {
1.1       misho     202:                        DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
1.1.1.2   misho     203:                        SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
1.1       misho     204:                        goto infile_error;
                    205:                }
                    206:        }
                    207: 
                    208:        /* send empty packet for eof */
1.1.1.2   misho     209:        if ((ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC)) == 0) {
                    210:                SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
1.1       misho     211:                goto infile_error;
                    212:        }
                    213: 
1.1.1.3   misho     214:        /* error during read occurred */
1.1       misho     215:        if (bufsize < 0) {
1.1.1.2   misho     216:                char tmp_buf[sizeof(conn->error_info->error)];
                    217:                int tmp_error_no;
1.1       misho     218:                *is_warning = TRUE;
                    219:                DBG_ERR_FMT("Bufsize < 0, warning,  %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
1.1.1.2   misho     220:                tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf) TSRMLS_CC);
                    221:                SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
1.1       misho     222:                goto infile_error;
                    223:        }
                    224: 
                    225:        result = PASS;
                    226: 
                    227: infile_error:
                    228:        /* get response from server and update upsert values */
                    229:        if (FAIL == conn->m->simple_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_QUERY, FALSE TSRMLS_CC)) {
                    230:                result = FAIL;
                    231:        }
                    232: 
                    233:        (*conn->infile.local_infile_end)(info TSRMLS_CC);
                    234:        if (buf) {
                    235:                mnd_efree(buf);
                    236:        }
                    237:        DBG_INF_FMT("%s", result == PASS? "PASS":"FAIL");
                    238:        DBG_RETURN(result);
                    239: }
                    240: /* }}} */
                    241: 
                    242: /*
                    243:  * Local variables:
                    244:  * tab-width: 4
                    245:  * c-basic-offset: 4
                    246:  * End:
                    247:  * vim600: noet sw=4 ts=4 fdm=marker
                    248:  * vim<600: noet sw=4 ts=4
                    249:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>