~drizzle-trunk/drizzle/development

390.1.4 by Monty Taylor
More copyright header file fixes.
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program 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
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
19
390.1.6 by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see...
20
#include <config.h>
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
21
383.1.44 by Monty Taylor
Renamed drizzle.h to libdrizzle.h.
22
#include "libdrizzle.h"
390.1.5 by Monty Taylor
Moved more functions into drizzle.c as part of the split of code.
23
#include "libdrizzle_priv.h"
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
24
#include "errmsg.h"
25
#include <sys/stat.h>
26
#include <signal.h>
27
#include <time.h>
390.1.6 by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see...
28
#include <fcntl.h>
29
#include <stdio.h>
30
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
31
#ifdef   HAVE_PWD_H
32
#include <pwd.h>
33
#endif
34
35
#include <sys/socket.h>
36
#include <netinet/in.h>
37
#include <arpa/inet.h>
38
#include <netdb.h>
39
#ifdef HAVE_SELECT_H
40
#include <select.h>
41
#endif
42
#ifdef HAVE_SYS_SELECT_H
43
#include <sys/select.h>
44
#endif
45
46
#ifdef HAVE_POLL
47
#include <sys/poll.h>
48
#endif
49
#ifdef HAVE_SYS_UN_H
50
#include <sys/un.h>
51
#endif
52
#ifndef INADDR_NONE
53
#define INADDR_NONE  -1
54
#endif
55
56
#include <sql_common.h>
383.1.49 by Monty Taylor
Got rid of client_settings.h
57
#include "local_infile.h"
390.1.5 by Monty Taylor
Moved more functions into drizzle.c as part of the split of code.
58
#include <libdrizzle/gettext.h>
383.1.49 by Monty Taylor
Got rid of client_settings.h
59
390.1.6 by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see...
60
#define MY_ALIGN(A,L)	(((A) + (L) - 1) & ~((L) - 1))
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
61
62
bool handle_local_infile(DRIZZLE *drizzle, const char *net_filename)
63
{
64
  bool result= true;
395 by Brian Aker
Fixed uint/ushort issue in libdrizzle
65
  uint32_t packet_length=MY_ALIGN(drizzle->net.max_packet-16,IO_SIZE);
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
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
  {
390.1.6 by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see...
85
    drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
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
  {
390.1.6 by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see...
93
    (void)my_net_write(net,(const unsigned char*) "",0); /* Server needs one packet */
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
94
    net_flush(net);
390.1.6 by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see...
95
    strcpy(net->sqlstate, sqlstate_get_unknown());
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
  {
390.1.6 by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see...
108
    if (my_net_write(net, (unsigned char*) buf, readcount))
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
109
    {
110
      goto err;
111
    }
112
  }
113
114
  /* Send empty packet to mark end of file */
390.1.6 by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see...
115
  if (my_net_write(net, (const unsigned char*) "", 0) || net_flush(net))
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
116
  {
390.1.6 by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see...
117
    drizzle_set_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown());
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
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
333 by Monty Taylor
More mysys removes.
186
  if ((data->fd = open(tmp_name, O_RDONLY)) < 0)
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
187
  {
333 by Monty Taylor
More mysys removes.
188
    data->error_num= errno;
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
189
    snprintf(data->error_msg, sizeof(data->error_msg)-1,
331 by Monty Taylor
Removed more mysys errmsg links.
190
             _("File '%s' not found (Errcode: %d)"), tmp_name, data->error_num);
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
191
    return 1;
192
  }
193
  return 0; /* ok */
194
}
195
196
197
/*
198
  Read data for LOAD LOCAL INFILE
199
200
  SYNOPSIS
201
    default_local_infile_read()
202
    ptr      Points to handle allocated by _init
203
    buf      Read data here
204
    buf_len    Ammount of data to read
205
206
  RETURN
207
    > 0    number of bytes read
208
    == 0  End of data
209
    < 0    Error
210
*/
211
395 by Brian Aker
Fixed uint/ushort issue in libdrizzle
212
static int default_local_infile_read(void *ptr, char *buf, uint32_t buf_len)
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
213
{
214
  int count;
215
  default_local_infile_data*data = (default_local_infile_data *) ptr;
216
390.1.6 by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see...
217
  if ((count= (int) read(data->fd, (unsigned char *) buf, buf_len)) < 0)
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
218
  {
331 by Monty Taylor
Removed more mysys errmsg links.
219
    data->error_num= 2; /* the errmsg for not entire file read */
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
220
    snprintf(data->error_msg, sizeof(data->error_msg)-1,
331 by Monty Taylor
Removed more mysys errmsg links.
221
             _("Error reading file '%s' (Errcode: %d)"),
333 by Monty Taylor
More mysys removes.
222
             data->filename, errno);
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
223
  }
224
  return count;
225
}
226
227
228
/*
229
  Read data for LOAD LOCAL INFILE
230
231
  SYNOPSIS
232
    default_local_infile_end()
233
    ptr      Points to handle allocated by _init
234
      May be NULL if _init failed!
235
236
  RETURN
237
*/
238
239
static void default_local_infile_end(void *ptr)
240
{
241
  default_local_infile_data *data= (default_local_infile_data *) ptr;
242
  if (data)          /* If not error on open */
243
  {
244
    if (data->fd >= 0)
333 by Monty Taylor
More mysys removes.
245
      close(data->fd);
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
246
    free(ptr);
247
  }
248
}
249
250
251
/*
252
  Return error from LOAD LOCAL INFILE
253
254
  SYNOPSIS
255
    default_local_infile_end()
256
    ptr      Points to handle allocated by _init
257
      May be NULL if _init failed!
258
    error_msg    Store error text here
259
    error_msg_len  Max lenght of error_msg
260
261
  RETURN
262
    error message number
263
*/
264
265
static int
395 by Brian Aker
Fixed uint/ushort issue in libdrizzle
266
default_local_infile_error(void *ptr, char *error_msg, uint32_t error_msg_len)
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
267
{
268
  default_local_infile_data *data = (default_local_infile_data *) ptr;
269
  if (data)          /* If not error on open */
270
  {
240.1.5 by Toru Maesaka
Merge with head and conflicts resolved
271
    strncpy(error_msg, data->error_msg, error_msg_len);
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
272
    return data->error_num;
273
  }
274
  /* This can only happen if we got error on malloc of handle */
240.1.5 by Toru Maesaka
Merge with head and conflicts resolved
275
  strcpy(error_msg, ER(CR_OUT_OF_MEMORY));
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
276
  return CR_OUT_OF_MEMORY;
277
}
278
279
280
void
281
drizzle_set_local_infile_handler(DRIZZLE *drizzle,
282
                               int (*local_infile_init)(void **, const char *,
283
                               void *),
395 by Brian Aker
Fixed uint/ushort issue in libdrizzle
284
                               int (*local_infile_read)(void *, char *, uint32_t),
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
285
                               void (*local_infile_end)(void *),
395 by Brian Aker
Fixed uint/ushort issue in libdrizzle
286
                               int (*local_infile_error)(void *, char *, uint32_t),
236.3.8 by Andrey Hristov
Move local infile handling to a separate file
287
                               void *userdata)
288
{
289
  drizzle->options.local_infile_init=  local_infile_init;
290
  drizzle->options.local_infile_read=  local_infile_read;
291
  drizzle->options.local_infile_end=   local_infile_end;
292
  drizzle->options.local_infile_error= local_infile_error;
293
  drizzle->options.local_infile_userdata = userdata;
294
}
295
296
297
void drizzle_set_local_infile_default(DRIZZLE *drizzle)
298
{
299
  drizzle->options.local_infile_init=  default_local_infile_init;
300
  drizzle->options.local_infile_read=  default_local_infile_read;
301
  drizzle->options.local_infile_end=   default_local_infile_end;
302
  drizzle->options.local_infile_error= default_local_infile_error;
303
}