This source file includes following definitions.
- mysqlnd_local_infile_init
- mysqlnd_local_infile_read
- mysqlnd_local_infile_error
- mysqlnd_local_infile_end
- mysqlnd_local_infile_default
- mysqlnd_handle_local_infile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 static
30 int mysqlnd_local_infile_init(void ** ptr, const char * const filename)
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
45 if (PG(open_basedir)) {
46 if (php_check_open_basedir_ex(filename, 0) == -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
68 static
69 int mysqlnd_local_infile_read(void * ptr, zend_uchar * buf, unsigned int buf_len)
70 {
71 MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
72 int count;
73
74 DBG_ENTER("mysqlnd_local_infile_read");
75
76 count = (int) php_stream_read(info->fd, (char *) buf, buf_len);
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
89 static
90 int mysqlnd_local_infile_error(void * ptr, char *error_buf, unsigned int error_buf_len)
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
110 static
111 void mysqlnd_local_infile_end(void * ptr)
112 {
113 MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
114
115 if (info) {
116
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
128 void
129 mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn)
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
138
139 static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of local file";
140
141
142
143 enum_func_status
144 mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning)
145 {
146 zend_uchar *buf = NULL;
147 zend_uchar empty_packet[MYSQLND_HEADER_SIZE];
148 enum_func_status result = FAIL;
149 unsigned int buflen = 4096;
150 void *info = NULL;
151 int bufsize;
152 size_t ret;
153 MYSQLND_INFILE infile;
154 MYSQLND_NET * net = conn->net;
155
156 DBG_ENTER("mysqlnd_handle_local_infile");
157
158 if (!(conn->options->flags & CLIENT_LOCAL_FILES)) {
159 php_error_docref(NULL, E_WARNING, "LOAD DATA LOCAL INFILE forbidden");
160
161 ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info);
162 *is_warning = TRUE;
163 goto infile_error;
164 }
165
166 infile = conn->infile;
167
168 buf = (zend_uchar *) mnd_ecalloc(1, buflen);
169
170 *is_warning = FALSE;
171
172
173 if (infile.local_infile_init(&info, (char *)filename)) {
174 char tmp_buf[sizeof(conn->error_info->error)];
175 int tmp_error_no;
176 *is_warning = TRUE;
177
178 tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
179 SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
180
181 ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info);
182 goto infile_error;
183 }
184
185
186 while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE, buflen - MYSQLND_HEADER_SIZE)) > 0) {
187 if ((ret = net->data->m.send_ex(net, buf, bufsize, conn->stats, conn->error_info)) == 0) {
188 DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
189 SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
190 goto infile_error;
191 }
192 }
193
194
195 if ((ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info)) == 0) {
196 SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
197 goto infile_error;
198 }
199
200
201 if (bufsize < 0) {
202 char tmp_buf[sizeof(conn->error_info->error)];
203 int tmp_error_no;
204 *is_warning = TRUE;
205 DBG_ERR_FMT("Bufsize < 0, warning, %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
206 tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
207 SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
208 goto infile_error;
209 }
210
211 result = PASS;
212
213 infile_error:
214
215 if (FAIL == conn->m->simple_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_QUERY, FALSE)) {
216 result = FAIL;
217 }
218
219 (*conn->infile.local_infile_end)(info);
220 if (buf) {
221 mnd_efree(buf);
222 }
223 DBG_INF_FMT("%s", result == PASS? "PASS":"FAIL");
224 DBG_RETURN(result);
225 }
226
227
228
229
230
231
232
233
234
235