Annotation of embedaddon/php/ext/mysqlnd/mysqlnd_loaddata.c, revision 1.1.1.3
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 ! misho 5: | Copyright (c) 2006-2013 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>