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

1.1       misho       1: /*
                      2:   +----------------------------------------------------------------------+
                      3:   | PHP Version 5                                                        |
                      4:   +----------------------------------------------------------------------+
                      5:   | Copyright (c) 2006-2012 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: Georg Richter <georg@mysql.com>                             |
                     16:   |          Andrey Hristov <andrey@mysql.com>                           |
                     17:   |          Ulf Wendel <uwendel@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: 
                     29: #define ALLOC_CALLBACK_ARGS(a, b, c)\
                     30: if (c) {\
                     31:        a = (zval ***)safe_emalloc(c, sizeof(zval **), 0);\
                     32:        for (i = b; i < c; i++) {\
                     33:                a[i] = mnd_emalloc(sizeof(zval *));\
                     34:                MAKE_STD_ZVAL(*a[i]);\
                     35:        }\
                     36: }
                     37: 
                     38: #define FREE_CALLBACK_ARGS(a, b, c)\
                     39: if (a) {\
                     40:        for (i = b; i < c; i++) {\
                     41:                zval_ptr_dtor(a[i]);\
                     42:                mnd_efree(a[i]);\
                     43:        }\
                     44:        mnd_efree(a);\
                     45: }
                     46: 
                     47: /* {{{ mysqlnd_local_infile_init */
                     48: static
                     49: int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS_DC)
                     50: {
                     51:        MYSQLND_INFILE_INFO     *info;
                     52:        php_stream_context      *context = NULL;
                     53: 
                     54:        DBG_ENTER("mysqlnd_local_infile_init");
                     55: 
                     56:        info = ((MYSQLND_INFILE_INFO *)mnd_ecalloc(1, sizeof(MYSQLND_INFILE_INFO)));
                     57:        if (!info) {
                     58:                DBG_RETURN(1);
                     59:        }
                     60: 
                     61:        *ptr = info;
                     62: 
                     63:        /* check open_basedir */
                     64:        if (PG(open_basedir)) {
                     65:                if (php_check_open_basedir_ex(filename, 0 TSRMLS_CC) == -1) {
                     66:                        strcpy(info->error_msg, "open_basedir restriction in effect. Unable to open file");
                     67:                        info->error_no = CR_UNKNOWN_ERROR;
                     68:                        DBG_RETURN(1);
                     69:                }
                     70:        }
                     71: 
                     72:        info->filename = filename;
                     73:        info->fd = php_stream_open_wrapper_ex((char *)filename, "r", 0, NULL, context);
                     74: 
                     75:        if (info->fd == NULL) {
                     76:                snprintf((char *)info->error_msg, sizeof(info->error_msg), "Can't find file '%-.64s'.", filename);
                     77:                info->error_no = MYSQLND_EE_FILENOTFOUND;
                     78:                DBG_RETURN(1);
                     79:        }
                     80: 
                     81:        DBG_RETURN(0);
                     82: }
                     83: /* }}} */
                     84: 
                     85: 
                     86: /* {{{ mysqlnd_local_infile_read */
                     87: static
                     88: int mysqlnd_local_infile_read(void *ptr, char *buf, unsigned int buf_len TSRMLS_DC)
                     89: {
                     90:        MYSQLND_INFILE_INFO     *info = (MYSQLND_INFILE_INFO *)ptr;
                     91:        int count;
                     92: 
                     93:        DBG_ENTER("mysqlnd_local_infile_read");
                     94: 
                     95:        count = (int)php_stream_read(info->fd, buf, buf_len);
                     96: 
                     97:        if (count < 0) {
                     98:                strcpy(info->error_msg, "Error reading file");
                     99:                info->error_no = CR_UNKNOWN_ERROR;
                    100:        }
                    101: 
                    102:        DBG_RETURN(count);
                    103: }
                    104: /* }}} */
                    105: 
                    106: 
                    107: /* {{{ mysqlnd_local_infile_error */
                    108: static
                    109: int    mysqlnd_local_infile_error(void *ptr, char *error_buf, unsigned int error_buf_len TSRMLS_DC)
                    110: {
                    111:        MYSQLND_INFILE_INFO     *info = (MYSQLND_INFILE_INFO *)ptr;
                    112: 
                    113:        DBG_ENTER("mysqlnd_local_infile_error");
                    114: 
                    115:        if (info) {
                    116:                strlcpy(error_buf, info->error_msg, error_buf_len);
                    117:                DBG_INF_FMT("have info, %d", info->error_no);
                    118:                DBG_RETURN(info->error_no);
                    119:        }
                    120: 
                    121:        strlcpy(error_buf, "Unknown error", error_buf_len);
                    122:        DBG_INF_FMT("no info, %d", CR_UNKNOWN_ERROR);
                    123:        DBG_RETURN(CR_UNKNOWN_ERROR);
                    124: }
                    125: /* }}} */
                    126: 
                    127: 
                    128: /* {{{ mysqlnd_local_infile_end */
                    129: static
                    130: void mysqlnd_local_infile_end(void *ptr TSRMLS_DC)
                    131: {
                    132:        MYSQLND_INFILE_INFO     *info = (MYSQLND_INFILE_INFO *)ptr;
                    133: 
                    134:        if (info) {
                    135:                /* php_stream_close segfaults on NULL */
                    136:                if (info->fd) {
                    137:                        php_stream_close(info->fd);
                    138:                        info->fd = NULL;
                    139:                }
                    140:                mnd_efree(info);
                    141:        }
                    142: }
                    143: /* }}} */
                    144: 
                    145: 
                    146: /* {{{ mysqlnd_local_infile_default */
                    147: PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn)
                    148: {
                    149:        conn->infile.local_infile_init = mysqlnd_local_infile_init;
                    150:        conn->infile.local_infile_read = mysqlnd_local_infile_read;
                    151:        conn->infile.local_infile_error = mysqlnd_local_infile_error;
                    152:        conn->infile.local_infile_end = mysqlnd_local_infile_end;
                    153: }
                    154: /* }}} */
                    155: 
                    156: /* {{{ mysqlnd_set_local_infile_handler */
                    157: PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char * const funcname)
                    158: {
                    159:        if (!conn->infile.callback) {
                    160:                MAKE_STD_ZVAL(conn->infile.callback);
                    161:        } else {
                    162:                zval_dtor(conn->infile.callback);
                    163:        }
                    164:        ZVAL_STRING(conn->infile.callback, (char*) funcname, 1);
                    165: }
                    166: /* }}} */
                    167: 
                    168: 
                    169: static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of local file";
                    170: 
                    171: 
                    172: /* {{{ mysqlnd_handle_local_infile */
                    173: enum_func_status
                    174: mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC)
                    175: {
                    176:        char                            *buf = NULL;
                    177:        char                            empty_packet[MYSQLND_HEADER_SIZE];
                    178:        enum_func_status        result = FAIL;
                    179:        unsigned int            buflen = 4096;
                    180:        void                            *info = NULL;
                    181:        int                                     bufsize;
                    182:        size_t                          ret;
                    183:        MYSQLND_INFILE          infile;
                    184: 
                    185:        DBG_ENTER("mysqlnd_handle_local_infile");
                    186: 
                    187:        if (!(conn->options.flags & CLIENT_LOCAL_FILES)) {
                    188:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "LOAD DATA LOCAL INFILE forbidden");
                    189:                /* write empty packet to server */
                    190:                ret = conn->net->m.send(conn, empty_packet, 0 TSRMLS_CC);
                    191:                *is_warning = TRUE;
                    192:                goto infile_error;
                    193:        }
                    194: 
                    195:        infile = conn->infile;
                    196:        /* allocate buffer for reading data */
                    197:        buf = (char *)mnd_ecalloc(1, buflen);
                    198: 
                    199:        *is_warning = FALSE;
                    200: 
                    201:        /* init handler: allocate read buffer and open file */
                    202:        if (infile.local_infile_init(&info, (char *)filename, conn->infile.userdata TSRMLS_CC)) {
                    203:                *is_warning = TRUE;
                    204:                /* error occured */
                    205:                strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
                    206:                conn->error_info.error_no =
                    207:                                infile.local_infile_error(info, conn->error_info.error, sizeof(conn->error_info.error) TSRMLS_CC);
                    208:                /* write empty packet to server */
                    209:                ret = conn->net->m.send(conn, empty_packet, 0 TSRMLS_CC);
                    210:                goto infile_error;
                    211:        }
                    212: 
                    213:        /* read data */
                    214:        while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE, buflen - MYSQLND_HEADER_SIZE TSRMLS_CC)) > 0) {
                    215:                if ((ret = conn->net->m.send(conn, buf, bufsize TSRMLS_CC)) == 0) {
                    216:                        DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
                    217:                        SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
                    218:                        goto infile_error;
                    219:                }
                    220:        }
                    221: 
                    222:        /* send empty packet for eof */
                    223:        if ((ret = conn->net->m.send(conn, empty_packet, 0 TSRMLS_CC)) == 0) {
                    224:                SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
                    225:                goto infile_error;
                    226:        }
                    227: 
                    228:        /* error during read occured */
                    229:        if (bufsize < 0) {
                    230:                *is_warning = TRUE;
                    231:                DBG_ERR_FMT("Bufsize < 0, warning,  %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
                    232:                strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
                    233:                conn->error_info.error_no =
                    234:                                infile.local_infile_error(info, conn->error_info.error, sizeof(conn->error_info.error) TSRMLS_CC);
                    235:                goto infile_error;
                    236:        }
                    237: 
                    238:        result = PASS;
                    239: 
                    240: infile_error:
                    241:        /* get response from server and update upsert values */
                    242:        if (FAIL == conn->m->simple_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_QUERY, FALSE TSRMLS_CC)) {
                    243:                result = FAIL;
                    244:        }
                    245: 
                    246:        (*conn->infile.local_infile_end)(info TSRMLS_CC);
                    247:        if (buf) {
                    248:                mnd_efree(buf);
                    249:        }
                    250:        DBG_INF_FMT("%s", result == PASS? "PASS":"FAIL");
                    251:        DBG_RETURN(result);
                    252: }
                    253: /* }}} */
                    254: 
                    255: /*
                    256:  * Local variables:
                    257:  * tab-width: 4
                    258:  * c-basic-offset: 4
                    259:  * End:
                    260:  * vim600: noet sw=4 ts=4 fdm=marker
                    261:  * vim<600: noet sw=4 ts=4
                    262:  */

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