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>