1/************************************************************************************
2 Copyright (C) 2000, 2011 MySQL AB & MySQL Finland AB & TCX DataKonsult AB,
3 Monty Program AB
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not see <http://www.gnu.org/licenses>
17 or write to the Free Software Foundation, Inc.,
18 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
19
20 Part of this code includes code from the PHP project which
21 is freely available from http://www.php.net
22*************************************************************************************/
23/*
24 +----------------------------------------------------------------------+
25 | PHP Version 5 |
26 +----------------------------------------------------------------------+
27 | Copyright (c) 2006-2011 The PHP Group |
28 +----------------------------------------------------------------------+
29 | This source file is subject to version 3.01 of the PHP license, |
30 | that is bundled with this package in the file LICENSE, and is |
31 | available through the world-wide-web at the following url: |
32 | http://www.php.net/license/3_01.txt |
33 | If you did not receive a copy of the PHP license and are unable to |
34 | obtain it through the world-wide-web, please send a note to |
35 | license@php.net so we can mail you a copy immediately. |
36 +----------------------------------------------------------------------+
37 | Authors: Georg Richter <georg@mysql.com> |
38 | Andrey Hristov <andrey@mysql.com> |
39 | Ulf Wendel <uwendel@mysql.com> |
40 +----------------------------------------------------------------------+
41*/
42
43#include "ma_global.h"
44#include <ma_sys.h>
45#include <ma_string.h>
46#include "errmsg.h"
47#include "mysql.h"
48#include <mariadb/ma_io.h>
49#include <string.h>
50#ifdef _WIN32
51#include <share.h>
52#endif
53#include <ma_common.h>
54
55typedef struct st_mysql_infile_info
56{
57 MA_FILE *fp;
58 int error_no;
59 char error_msg[MYSQL_ERRMSG_SIZE + 1];
60 const char *filename;
61} MYSQL_INFILE_INFO;
62
63/* {{{ mysql_local_infile_init */
64static
65int mysql_local_infile_init(void **ptr, const char *filename, void *userdata)
66{
67 MYSQL_INFILE_INFO *info;
68 MYSQL *mysql= (MYSQL *)userdata;
69
70 info = (MYSQL_INFILE_INFO *)malloc(sizeof(MYSQL_INFILE_INFO));
71 if (!info) {
72 return(1);
73 }
74 memset(info, 0, sizeof(MYSQL_INFILE_INFO));
75 *ptr = info;
76
77 info->filename = filename;
78
79 info->fp= ma_open(filename, "rb", mysql);
80
81 if (!info->fp)
82 {
83 /* error handling is done via mysql_local_infile_error function, so we
84 need to copy error to info */
85 if (mysql_errno(mysql) && !info->error_no)
86 {
87 info->error_no= mysql_errno(mysql);
88 ma_strmake(info->error_msg, mysql_error(mysql), MYSQL_ERRMSG_SIZE);
89 }
90 else
91 {
92 info->error_no = errno;
93 snprintf((char *)info->error_msg, sizeof(info->error_msg),
94 CER(CR_FILE_NOT_FOUND), filename, info->error_no);
95 }
96 return(1);
97 }
98
99 return(0);
100}
101/* }}} */
102
103
104/* {{{ mysql_local_infile_read */
105static
106int mysql_local_infile_read(void *ptr, char * buf, unsigned int buf_len)
107{
108 MYSQL_INFILE_INFO *info = (MYSQL_INFILE_INFO *)ptr;
109 size_t count;
110
111 count= ma_read((void *)buf, 1, (size_t)buf_len, info->fp);
112
113 if (count == (size_t)-1)
114 {
115 info->error_no = errno;
116 snprintf((char *)info->error_msg, sizeof(info->error_msg),
117 CER(CR_FILE_READ), info->filename, info->error_no);
118 }
119 return((int)count);
120}
121/* }}} */
122
123
124/* {{{ mysql_local_infile_error */
125static
126int mysql_local_infile_error(void *ptr, char *error_buf, unsigned int error_buf_len)
127{
128 MYSQL_INFILE_INFO *info = (MYSQL_INFILE_INFO *)ptr;
129
130 if (info) {
131 ma_strmake(error_buf, info->error_msg, error_buf_len);
132 return(info->error_no);
133 }
134
135 ma_strmake(error_buf, "Unknown error", error_buf_len);
136 return(CR_UNKNOWN_ERROR);
137}
138/* }}} */
139
140
141/* {{{ mysql_local_infile_end */
142static
143void mysql_local_infile_end(void *ptr)
144{
145 MYSQL_INFILE_INFO *info = (MYSQL_INFILE_INFO *)ptr;
146
147 if (info)
148 {
149 if (info->fp)
150 ma_close(info->fp);
151 free(ptr);
152 }
153 return;
154}
155/* }}} */
156
157
158/* {{{ mysql_local_infile_default */
159void mysql_set_local_infile_default(MYSQL *conn)
160{
161 conn->options.local_infile_init = mysql_local_infile_init;
162 conn->options.local_infile_read = mysql_local_infile_read;
163 conn->options.local_infile_error = mysql_local_infile_error;
164 conn->options.local_infile_end = mysql_local_infile_end;
165 return;
166}
167/* }}} */
168
169/* {{{ mysql_set_local_infile_handler */
170void STDCALL mysql_set_local_infile_handler(MYSQL *conn,
171 int (*local_infile_init)(void **, const char *, void *),
172 int (*local_infile_read)(void *, char *, uint),
173 void (*local_infile_end)(void *),
174 int (*local_infile_error)(void *, char *, uint),
175 void *userdata)
176{
177 conn->options.local_infile_init= local_infile_init;
178 conn->options.local_infile_read= local_infile_read;
179 conn->options.local_infile_end= local_infile_end;
180 conn->options.local_infile_error= local_infile_error;
181 conn->options.local_infile_userdata = userdata;
182 return;
183}
184/* }}} */
185
186/* {{{ mysql_handle_local_infile */
187my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename, my_bool can_local_infile)
188{
189 unsigned int buflen= 4096;
190 int bufread;
191 unsigned char *buf= NULL;
192 void *info= NULL;
193 my_bool result= 1;
194
195 /* check if all callback functions exist */
196 if (!conn->options.local_infile_init || !conn->options.local_infile_end ||
197 !conn->options.local_infile_read || !conn->options.local_infile_error)
198 {
199 conn->options.local_infile_userdata= conn;
200 mysql_set_local_infile_default(conn);
201 }
202
203 if (!(conn->options.client_flag & CLIENT_LOCAL_FILES) ||
204 !can_local_infile)
205 {
206 my_set_error(conn, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "Load data local infile forbidden");
207 /* write empty packet to server */
208 ma_net_write(&conn->net, (unsigned char *)"", 0);
209 ma_net_flush(&conn->net);
210 goto infile_error;
211 }
212
213 /* allocate buffer for reading data */
214 buf = (uchar *)malloc(buflen);
215
216 /* init handler: allocate read buffer and open file */
217 if (conn->options.local_infile_init(&info, filename,
218 conn->options.local_infile_userdata))
219 {
220 char tmp_buf[MYSQL_ERRMSG_SIZE];
221 int tmp_errno;
222
223 tmp_errno= conn->options.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
224 my_set_error(conn, tmp_errno, SQLSTATE_UNKNOWN, tmp_buf);
225 ma_net_write(&conn->net, (unsigned char *)"", 0);
226 ma_net_flush(&conn->net);
227 goto infile_error;
228 }
229
230 /* read data */
231 while ((bufread= conn->options.local_infile_read(info, (char *)buf, buflen)) > 0)
232 {
233 if (ma_net_write(&conn->net, (unsigned char *)buf, bufread))
234 {
235 my_set_error(conn, CR_SERVER_LOST, SQLSTATE_UNKNOWN, NULL);
236 goto infile_error;
237 }
238 }
239
240 /* send empty packet for eof */
241 if (ma_net_write(&conn->net, (unsigned char *)"", 0) ||
242 ma_net_flush(&conn->net))
243 {
244 my_set_error(conn, CR_SERVER_LOST, SQLSTATE_UNKNOWN, NULL);
245 goto infile_error;
246 }
247
248 /* error during read occurred */
249 if (bufread < 0)
250 {
251 char tmp_buf[MYSQL_ERRMSG_SIZE];
252 int tmp_errno= conn->options.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
253 my_set_error(conn, tmp_errno, SQLSTATE_UNKNOWN, tmp_buf);
254 goto infile_error;
255 }
256
257 result = 0;
258
259infile_error:
260 conn->options.local_infile_end(info);
261 free(buf);
262 return(result);
263}
264/* }}} */
265
266