~drizzle-trunk/drizzle/development

236.3.8 by Andrey Hristov
Move local infile handling to a separate file
1
/* Copyright (C) 2000-2004 DRIZZLE AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation.
6
7
   There are special exceptions to the terms and conditions of the GPL as it
8
   is applied to this software. View the full text of the exception in file
9
   EXCEPTIONS-CLIENT in the directory of this software distribution.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
19
20
21
#include <drizzled/global.h>
22
#include <mysys/my_sys.h>
23
#include "my_time.h"
236.1.32 by Monty Taylor
Couple of small post-merge fixes.
24
#include <mysys/mysys_err.h>
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
25
#include <mystrings/m_string.h>
26
#include <mystrings/m_ctype.h>
27
#include "drizzle.h"
28
#include "errmsg.h"
236.1.32 by Monty Taylor
Couple of small post-merge fixes.
29
#include <vio/violite.h>
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
30
#include <sys/stat.h>
31
#include <signal.h>
32
#include <time.h>
33
#ifdef   HAVE_PWD_H
34
#include <pwd.h>
35
#endif
36
37
#include <sys/socket.h>
38
#include <netinet/in.h>
39
#include <arpa/inet.h>
40
#include <netdb.h>
41
#ifdef HAVE_SELECT_H
42
#include <select.h>
43
#endif
44
#ifdef HAVE_SYS_SELECT_H
45
#include <sys/select.h>
46
#endif
47
48
#ifdef HAVE_POLL
49
#include <sys/poll.h>
50
#endif
51
#ifdef HAVE_SYS_UN_H
52
#include <sys/un.h>
53
#endif
54
#ifndef INADDR_NONE
55
#define INADDR_NONE  -1
56
#endif
57
58
#include <sql_common.h>
59
#include "client_settings.h"
60
61
62
bool handle_local_infile(DRIZZLE *drizzle, const char *net_filename)
63
{
64
  bool result= true;
65
  uint packet_length=MY_ALIGN(drizzle->net.max_packet-16,IO_SIZE);
66
  NET *net= &drizzle->net;
67
  int readcount;
68
  void *li_ptr;          /* pass state to local_infile functions */
69
  char *buf;    /* buffer to be filled by local_infile_read */
70
  struct st_drizzle_options *options= &drizzle->options;
71
72
  /* check that we've got valid callback functions */
73
  if (!(options->local_infile_init &&
74
  options->local_infile_read &&
75
  options->local_infile_end &&
76
  options->local_infile_error))
77
  {
78
    /* if any of the functions is invalid, set the default */
79
    drizzle_set_local_infile_default(drizzle);
80
  }
81
82
  /* copy filename into local memory and allocate read buffer */
83
  if (!(buf=malloc(packet_length)))
84
  {
85
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
86
    return(1);
87
  }
88
89
  /* initialize local infile (open file, usually) */
90
  if ((*options->local_infile_init)(&li_ptr, net_filename,
91
    options->local_infile_userdata))
92
  {
93
    VOID(my_net_write(net,(const uchar*) "",0)); /* Server needs one packet */
94
    net_flush(net);
240.1.5 by Toru Maesaka
Merge with head and conflicts resolved
95
    strcpy(net->sqlstate, unknown_sqlstate);
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
96
    net->last_errno=
97
      (*options->local_infile_error)(li_ptr,
98
                                     net->last_error,
99
                                     sizeof(net->last_error)-1);
100
    goto err;
101
  }
102
103
  /* read blocks of data from local infile callback */
104
  while ((readcount =
105
    (*options->local_infile_read)(li_ptr, buf,
106
          packet_length)) > 0)
107
  {
108
    if (my_net_write(net, (uchar*) buf, readcount))
109
    {
110
      goto err;
111
    }
112
  }
113
114
  /* Send empty packet to mark end of file */
115
  if (my_net_write(net, (const uchar*) "", 0) || net_flush(net))
116
  {
117
    set_drizzle_error(drizzle, CR_SERVER_LOST, unknown_sqlstate);
118
    goto err;
119
  }
120
121
  if (readcount < 0)
122
  {
123
    net->last_errno=
124
      (*options->local_infile_error)(li_ptr,
125
                                     net->last_error,
126
                                     sizeof(net->last_error)-1);
127
    goto err;
128
  }
129
130
  result=false;					/* Ok */
131
132
err:
133
  /* free up memory allocated with _init, usually */
134
  (*options->local_infile_end)(li_ptr);
135
  if(buf)
136
    free(buf);
137
  return(result);
138
}
139
140
141
/****************************************************************************
142
  Default handlers for LOAD LOCAL INFILE
143
****************************************************************************/
144
145
typedef struct st_default_local_infile
146
{
147
  int fd;
148
  int error_num;
149
  const char *filename;
150
  char error_msg[LOCAL_INFILE_ERROR_LEN];
151
} default_local_infile_data;
152
153
154
/*
155
  Open file for LOAD LOCAL INFILE
156
157
  SYNOPSIS
158
    default_local_infile_init()
159
    ptr      Store pointer to internal data here
160
    filename    File name to open. This may be in unix format !
161
162
163
  NOTES
164
    Even if this function returns an error, the load data interface
165
    guarantees that default_local_infile_end() is called.
166
167
  RETURN
168
    0  ok
169
    1  error
170
*/
171
172
static int default_local_infile_init(void **ptr, const char *filename,
173
             void *userdata __attribute__ ((unused)))
174
{
175
  default_local_infile_data *data;
176
  char tmp_name[FN_REFLEN];
177
178
  if (!(*ptr= data= ((default_local_infile_data *)
179
		     malloc(sizeof(default_local_infile_data)))))
180
    return 1; /* out of memory */
181
182
  data->error_msg[0]= 0;
183
  data->error_num=    0;
184
  data->filename= filename;
185
186
  fn_format(tmp_name, filename, "", "", MY_UNPACK_FILENAME);
187
  if ((data->fd = my_open(tmp_name, O_RDONLY, MYF(0))) < 0)
188
  {
189
    data->error_num= my_errno;
190
    snprintf(data->error_msg, sizeof(data->error_msg)-1,
191
             EE(EE_FILENOTFOUND), tmp_name, data->error_num);
192
    return 1;
193
  }
194
  return 0; /* ok */
195
}
196
197
198
/*
199
  Read data for LOAD LOCAL INFILE
200
201
  SYNOPSIS
202
    default_local_infile_read()
203
    ptr      Points to handle allocated by _init
204
    buf      Read data here
205
    buf_len    Ammount of data to read
206
207
  RETURN
208
    > 0    number of bytes read
209
    == 0  End of data
210
    < 0    Error
211
*/
212
213
static int default_local_infile_read(void *ptr, char *buf, uint buf_len)
214
{
215
  int count;
216
  default_local_infile_data*data = (default_local_infile_data *) ptr;
217
218
  if ((count= (int) my_read(data->fd, (uchar *) buf, buf_len, MYF(0))) < 0)
219
  {
220
    data->error_num= EE_READ; /* the errmsg for not entire file read */
221
    snprintf(data->error_msg, sizeof(data->error_msg)-1,
222
             EE(EE_READ),
223
             data->filename, my_errno);
224
  }
225
  return count;
226
}
227
228
229
/*
230
  Read data for LOAD LOCAL INFILE
231
232
  SYNOPSIS
233
    default_local_infile_end()
234
    ptr      Points to handle allocated by _init
235
      May be NULL if _init failed!
236
237
  RETURN
238
*/
239
240
static void default_local_infile_end(void *ptr)
241
{
242
  default_local_infile_data *data= (default_local_infile_data *) ptr;
243
  if (data)          /* If not error on open */
244
  {
245
    if (data->fd >= 0)
246
      my_close(data->fd, MYF(MY_WME));
247
    free(ptr);
248
  }
249
}
250
251
252
/*
253
  Return error from LOAD LOCAL INFILE
254
255
  SYNOPSIS
256
    default_local_infile_end()
257
    ptr      Points to handle allocated by _init
258
      May be NULL if _init failed!
259
    error_msg    Store error text here
260
    error_msg_len  Max lenght of error_msg
261
262
  RETURN
263
    error message number
264
*/
265
266
static int
267
default_local_infile_error(void *ptr, char *error_msg, uint error_msg_len)
268
{
269
  default_local_infile_data *data = (default_local_infile_data *) ptr;
270
  if (data)          /* If not error on open */
271
  {
240.1.5 by Toru Maesaka
Merge with head and conflicts resolved
272
    strncpy(error_msg, data->error_msg, error_msg_len);
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
273
    return data->error_num;
274
  }
275
  /* This can only happen if we got error on malloc of handle */
240.1.5 by Toru Maesaka
Merge with head and conflicts resolved
276
  strcpy(error_msg, ER(CR_OUT_OF_MEMORY));
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
277
  return CR_OUT_OF_MEMORY;
278
}
279
280
281
void
282
drizzle_set_local_infile_handler(DRIZZLE *drizzle,
283
                               int (*local_infile_init)(void **, const char *,
284
                               void *),
285
                               int (*local_infile_read)(void *, char *, uint),
286
                               void (*local_infile_end)(void *),
287
                               int (*local_infile_error)(void *, char *, uint),
288
                               void *userdata)
289
{
290
  drizzle->options.local_infile_init=  local_infile_init;
291
  drizzle->options.local_infile_read=  local_infile_read;
292
  drizzle->options.local_infile_end=   local_infile_end;
293
  drizzle->options.local_infile_error= local_infile_error;
294
  drizzle->options.local_infile_userdata = userdata;
295
}
296
297
298
void drizzle_set_local_infile_default(DRIZZLE *drizzle)
299
{
300
  drizzle->options.local_infile_init=  default_local_infile_init;
301
  drizzle->options.local_infile_read=  default_local_infile_read;
302
  drizzle->options.local_infile_end=   default_local_infile_end;
303
  drizzle->options.local_infile_error= default_local_infile_error;
304
}