Annotation of embedaddon/php/ext/mysqlnd/mysqlnd_loaddata.c, revision 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>