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>