~ubuntu-branches/ubuntu/quantal/php5/quantal

« back to all changes in this revision

Viewing changes to ext/mysqlnd/mysqlnd_loaddata.c

  • Committer: Bazaar Package Importer
  • Author(s): Sean Finney
  • Date: 2009-07-01 09:12:10 UTC
  • mto: (0.9.1) (1.1.17 upstream)
  • mto: This revision was merged to the branch mainline in revision 58.
  • Revision ID: james.westby@ubuntu.com-20090701091210-go0h6506p62on17r
Tags: upstream-5.3.0
ImportĀ upstreamĀ versionĀ 5.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  +----------------------------------------------------------------------+
 
3
  | PHP Version 6                                                        |
 
4
  +----------------------------------------------------------------------+
 
5
  | Copyright (c) 2006-2009 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
enum_func_status mysqlnd_simple_command_handle_response(MYSQLND *conn,
 
29
                                                                                enum php_mysql_packet_type ok_packet,
 
30
                                                                                zend_bool silent, enum php_mysqlnd_server_command command,
 
31
                                                                                zend_bool ignore_upsert_status
 
32
                                                                                TSRMLS_DC);
 
33
 
 
34
 
 
35
#define ALLOC_CALLBACK_ARGS(a, b, c)\
 
36
if (c) {\
 
37
        a = (zval ***)safe_emalloc(c, sizeof(zval **), 0);\
 
38
        for (i = b; i < c; i++) {\
 
39
                a[i] = mnd_emalloc(sizeof(zval *));\
 
40
                MAKE_STD_ZVAL(*a[i]);\
 
41
        }\
 
42
}
 
43
 
 
44
#define FREE_CALLBACK_ARGS(a, b, c)\
 
45
if (a) {\
 
46
        for (i=b; i < c; i++) {\
 
47
                zval_ptr_dtor(a[i]);\
 
48
                mnd_efree(a[i]);\
 
49
        }\
 
50
        mnd_efree(a);\
 
51
}
 
52
 
 
53
/* {{{ mysqlnd_local_infile_init */
 
54
static
 
55
int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS_DC)
 
56
{
 
57
        MYSQLND_INFILE_INFO             *info;
 
58
        php_stream_context              *context = NULL;
 
59
 
 
60
        DBG_ENTER("mysqlnd_local_infile_init");
 
61
 
 
62
        *ptr = info = ((MYSQLND_INFILE_INFO *)mnd_ecalloc(1, sizeof(MYSQLND_INFILE_INFO)));
 
63
 
 
64
        /* check open_basedir */
 
65
        if (PG(open_basedir)) {
 
66
                if (php_check_open_basedir_ex(filename, 0 TSRMLS_CC) == -1) {
 
67
                        strcpy(info->error_msg, "open_basedir restriction in effect. Unable to open file");
 
68
                        info->error_no = CR_UNKNOWN_ERROR;
 
69
                        DBG_RETURN(1);
 
70
                }
 
71
        }
 
72
 
 
73
        info->filename = filename;
 
74
        info->fd = php_stream_open_wrapper_ex((char *)filename, "r", 0, NULL, context);
 
75
 
 
76
        if (info->fd == NULL) {
 
77
                snprintf((char *)info->error_msg, sizeof(info->error_msg), "Can't find file '%-.64s'.", filename);
 
78
                info->error_no = MYSQLND_EE_FILENOTFOUND; 
 
79
                DBG_RETURN(1);
 
80
        }
 
81
 
 
82
        DBG_RETURN(0);
 
83
}
 
84
/* }}} */
 
85
 
 
86
 
 
87
/* {{{ mysqlnd_local_infile_read */
 
88
static
 
89
int mysqlnd_local_infile_read(void *ptr, char *buf, unsigned int buf_len TSRMLS_DC)
 
90
{
 
91
        MYSQLND_INFILE_INFO     *info = (MYSQLND_INFILE_INFO *)ptr;
 
92
        int count;
 
93
 
 
94
    DBG_ENTER("mysqlnd_local_infile_read");
 
95
 
 
96
        count = (int)php_stream_read(info->fd, buf, buf_len);
 
97
 
 
98
        if (count < 0) {
 
99
                strcpy(info->error_msg, "Error reading file");
 
100
                info->error_no = CR_UNKNOWN_ERROR;
 
101
        }
 
102
 
 
103
        DBG_RETURN(count);
 
104
}
 
105
/* }}} */
 
106
 
 
107
 
 
108
/* {{{ mysqlnd_local_infile_error */
 
109
static
 
110
int     mysqlnd_local_infile_error(void *ptr, char *error_buf, unsigned int error_buf_len TSRMLS_DC)
 
111
{
 
112
        MYSQLND_INFILE_INFO     *info = (MYSQLND_INFILE_INFO *)ptr;
 
113
 
 
114
        DBG_ENTER("mysqlnd_local_infile_error");
 
115
 
 
116
        if (info) {
 
117
                strlcpy(error_buf, info->error_msg, error_buf_len);
 
118
                DBG_INF_FMT("have info, %d", info->error_no);
 
119
                DBG_RETURN(info->error_no);
 
120
        }
 
121
 
 
122
        strlcpy(error_buf, "Unknown error", error_buf_len);
 
123
        DBG_INF_FMT("no info, %d", CR_UNKNOWN_ERROR);
 
124
        DBG_RETURN(CR_UNKNOWN_ERROR);
 
125
}
 
126
/* }}} */
 
127
 
 
128
 
 
129
/* {{{ mysqlnd_local_infile_end */
 
130
static
 
131
void mysqlnd_local_infile_end(void *ptr TSRMLS_DC)
 
132
{
 
133
        MYSQLND_INFILE_INFO     *info = (MYSQLND_INFILE_INFO *)ptr;
 
134
 
 
135
        if (info) {
 
136
                /* php_stream_close segfaults on NULL */
 
137
                if (info->fd) {
 
138
                        php_stream_close(info->fd);
 
139
                        info->fd = NULL;
 
140
                }
 
141
                mnd_efree(info);
 
142
        }
 
143
}
 
144
/* }}} */
 
145
 
 
146
 
 
147
/* {{{ mysqlnd_local_infile_default */
 
148
PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn)
 
149
{
 
150
        conn->infile.local_infile_init = mysqlnd_local_infile_init;
 
151
        conn->infile.local_infile_read = mysqlnd_local_infile_read;
 
152
        conn->infile.local_infile_error = mysqlnd_local_infile_error;
 
153
        conn->infile.local_infile_end = mysqlnd_local_infile_end;
 
154
}
 
155
/* }}} */
 
156
 
 
157
/* {{{ mysqlnd_set_local_infile_handler */
 
158
PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char * const funcname)
 
159
{
 
160
        if (!conn->infile.callback) {
 
161
                MAKE_STD_ZVAL(conn->infile.callback);
 
162
        } else {
 
163
                zval_dtor(conn->infile.callback);
 
164
        }
 
165
        ZVAL_STRING(conn->infile.callback, (char*) funcname, 1);
 
166
}
 
167
/* }}} */
 
168
 
 
169
 
 
170
static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of local file";
 
171
 
 
172
 
 
173
/* {{{ mysqlnd_handle_local_infile */
 
174
enum_func_status
 
175
mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC)
 
176
{
 
177
        char                            *buf;
 
178
        char                            empty_packet[MYSQLND_HEADER_SIZE];
 
179
        enum_func_status        result = FAIL;
 
180
        unsigned int                            buflen = 4096;
 
181
        void                            *info = NULL;
 
182
        int                                     bufsize;
 
183
        size_t                          ret;
 
184
        MYSQLND_INFILE          infile;
 
185
 
 
186
        DBG_ENTER("mysqlnd_handle_local_infile");
 
187
 
 
188
        if (!(conn->options.flags & CLIENT_LOCAL_FILES)) {
 
189
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "LOAD DATA LOCAL INFILE forbidden");
 
190
                /* write empty packet to server */
 
191
                ret = mysqlnd_stream_write_w_header(conn, empty_packet, 0 TSRMLS_CC);
 
192
                *is_warning = TRUE;
 
193
                goto infile_error;
 
194
        }
 
195
 
 
196
        infile = conn->infile;
 
197
        /* allocate buffer for reading data */
 
198
        buf = (char *)mnd_ecalloc(1, buflen);
 
199
        
 
200
        *is_warning = FALSE;
 
201
 
 
202
        /* init handler: allocate read buffer and open file */
 
203
        if (infile.local_infile_init(&info, (char *)filename, conn->infile.userdata TSRMLS_CC)) {
 
204
                *is_warning = TRUE;
 
205
                /* error occured */
 
206
                strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
 
207
                conn->error_info.error_no =
 
208
                                infile.local_infile_error(info, conn->error_info.error,
 
209
                                                                                  sizeof(conn->error_info.error) TSRMLS_CC);
 
210
                /* write empty packet to server */
 
211
                ret = mysqlnd_stream_write_w_header(conn, empty_packet, 0 TSRMLS_CC);
 
212
                goto infile_error;
 
213
        }
 
214
 
 
215
        /* read data */
 
216
        while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE,
 
217
                                                                                                buflen - MYSQLND_HEADER_SIZE TSRMLS_CC)) > 0) {
 
218
                if ((ret = mysqlnd_stream_write_w_header(conn, buf, bufsize TSRMLS_CC)) < 0) {
 
219
                        DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
 
220
                        SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
 
221
                        goto infile_error;
 
222
                }
 
223
        }
 
224
 
 
225
        /* send empty packet for eof */
 
226
        if ((ret = mysqlnd_stream_write_w_header(conn, empty_packet, 0 TSRMLS_CC)) < 0) {
 
227
                SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
 
228
                goto infile_error;
 
229
        }
 
230
 
 
231
        /* error during read occured */
 
232
        if (bufsize < 0) {
 
233
                *is_warning = TRUE;
 
234
                DBG_ERR_FMT("Bufsize < 0, warning,  %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
 
235
                strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
 
236
                conn->error_info.error_no = infile.local_infile_error(info, conn->error_info.error,
 
237
                                                                                                                         sizeof(conn->error_info.error) TSRMLS_CC);
 
238
                goto infile_error;
 
239
        }
 
240
 
 
241
        result = PASS;
 
242
 
 
243
infile_error:
 
244
        /* get response from server and update upsert values */
 
245
        if (FAIL == mysqlnd_simple_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_QUERY, FALSE TSRMLS_CC)) {
 
246
                result = FAIL;
 
247
        }
 
248
 
 
249
        (*conn->infile.local_infile_end)(info TSRMLS_CC);
 
250
        mnd_efree(buf);
 
251
        DBG_INF_FMT("%s", result == PASS? "PASS":"FAIL");
 
252
        DBG_RETURN(result);
 
253
}
 
254
/* }}} */
 
255
 
 
256
/*
 
257
 * Local variables:
 
258
 * tab-width: 4
 
259
 * c-basic-offset: 4
 
260
 * End:
 
261
 * vim600: noet sw=4 ts=4 fdm=marker
 
262
 * vim<600: noet sw=4 ts=4
 
263
 */