diff options
author | monty@mysql.com <> | 2004-03-25 22:11:22 +0200 |
---|---|---|
committer | monty@mysql.com <> | 2004-03-25 22:11:22 +0200 |
commit | 1448199bd75009ac9b4aa42c9d4fb8d827a4cb12 (patch) | |
tree | 36abf1d40f08cd21cd81f6d5966b89ab4e995ac6 /libmysql | |
parent | eb91f7b478938969b4a182aed5d624c2f8fce38a (diff) | |
download | mariadb-git-1448199bd75009ac9b4aa42c9d4fb8d827a4cb12.tar.gz |
Cleanups & safety fixes
Diffstat (limited to 'libmysql')
-rw-r--r-- | libmysql/libmysql.c | 222 |
1 files changed, 133 insertions, 89 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 357c85c09b2..9ad51518d83 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -799,54 +799,51 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename) my_bool result= 1; uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE); NET *net= &mysql->net; - int error; int readcount; void *li_ptr; /* pass state to local_infile functions */ - char *buf = NULL; /* buffer to be filled by local_infile_read */ - char *filename = NULL; /* local copy of filename arg */ - + char *buf;; /* buffer to be filled by local_infile_read */ + struct st_mysql_options *options= &mysql->options; DBUG_ENTER("handle_local_infile"); /* check that we've got valid callback functions */ - if (!((mysql->options.local_infile_init) && - (mysql->options.local_infile_read) && - (mysql->options.local_infile_end) && - (mysql->options.local_infile_error))) + if (!(options->local_infile_init && + options->local_infile_read && + options->local_infile_end && + options->local_infile_error)) { /* if any of the functions is invalid, set the default */ - mysql_set_local_infile_default(mysql); + mysql_set_local_infile_default(mysql); } /* copy filename into local memory and allocate read buffer */ - if ((!(filename = my_strdup(net_filename, MYF(0)))) || - (!(buf=my_malloc(packet_length, MYF(0))))) - goto oom; - + if (!(buf=my_malloc(packet_length, MYF(0)))) + { + strmov(net->sqlstate, unknown_sqlstate); + strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); + DBUG_RETURN(1); + } /* initialize local infile (open file, usually) */ - if ( (error = (*mysql->options.local_infile_init)(&li_ptr, filename)) ) + if ((*options->local_infile_init)(&li_ptr, net_filename)) { my_net_write(net,"",0); /* Server needs one packet */ net_flush(net); - if(error < 0) - goto oom; strmov(net->sqlstate, unknown_sqlstate); - net->last_errno=error; - (*mysql->options.local_infile_error)(li_ptr, - net->last_error, - sizeof(net->last_error)-1); + net->last_errno= (*options->local_infile_error)(li_ptr, + net->last_error, + sizeof(net->last_error)-1); goto err; } /* read blocks of data from local infile callback */ - while ( (readcount = - (*mysql->options.local_infile_read)(li_ptr, - buf, - packet_length) ) > 0) + while ((readcount = + (*options->local_infile_read)(li_ptr, buf, + packet_length)) > 0) { if (my_net_write(net,buf,readcount)) { - DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file")); + DBUG_PRINT("error", + ("Lost connection to MySQL server during LOAD DATA of local file")); strmov(net->sqlstate, unknown_sqlstate); net->last_errno=CR_SERVER_LOST; strmov(net->last_error,ER(net->last_errno)); @@ -865,10 +862,9 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename) if (readcount < 0) { - strmov(net->sqlstate, unknown_sqlstate); - net->last_errno=EE_READ; /* the errmsg for not entire file read */ - my_snprintf(net->last_error,sizeof(net->last_error)-1, - filename, errno); + net->last_errno= (*options->local_infile_error)(li_ptr, + net->last_error, + sizeof(net->last_error)-1); goto err; } @@ -876,117 +872,165 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename) err: /* free up memory allocated with _init, usually */ - (*mysql->options.local_infile_end)(li_ptr); - - my_free(filename, MYF(0)); - my_free(buf, MYF(0)); + (*options->local_infile_end)(li_ptr); DBUG_RETURN(result); - -oom: - /* out of memory */ - my_free(filename, MYF(MY_ALLOW_ZERO_PTR)); - my_free(buf, MYF(MY_ALLOW_ZERO_PTR)); - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); - DBUG_RETURN(1); } -typedef struct default_local_infile_st { +/**************************************************************************** + Default handlers for LOAD LOCAL INFILE +****************************************************************************/ + +typedef struct st_default_local_infile +{ int fd; int error_num; + const char *filename; char error_msg[LOCAL_INFILE_ERROR_LEN]; } default_local_infile_data; -int -default_local_infile_init(void **ptr, char *filename) +/* + Open file for LOAD LOCAL INFILE + + SYNOPSIS + default_local_infile_init() + ptr Store pointer to internal data here + filename File name to open. This may be in unix format ! + + + NOTES + Even if this function returns an error, the load data interface + guarantees that default_local_infile_end() is called. + + RETURN + 0 ok + 1 error +*/ + +static int default_local_infile_init(void **ptr, const char *filename) { default_local_infile_data *data; + char tmp_name[FN_REFLEN]; if (!(*ptr= data= ((default_local_infile_data *) - my_malloc(sizeof(default_local_infile_data), MYF(0))))) - return -1; /* out of memory */ - - *ptr = data; /* save the struct, we need it to return an error */ + my_malloc(sizeof(default_local_infile_data), MYF(0))))) + return 1; /* out of memory */ data->error_msg[0]= 0; data->error_num= 0; + data->filename= filename; - if ((data->fd = my_open(filename, O_RDONLY, MYF(0))) < 0) + fn_format(tmp_name, filename, "", "", MY_UNPACK_FILENAME); + if ((data->fd = my_open(tmp_name, O_RDONLY, MYF(0))) < 0) { + data->error_num= my_errno; my_snprintf(data->error_msg, sizeof(data->error_msg)-1, - EE(EE_FILENOTFOUND), filename, errno); - return data->error_num=errno; /* error */ + EE(EE_FILENOTFOUND), tmp_name, data->error_num); + return 1; } - return 0; /* ok */ } -int -default_local_infile_read(void *ptr, char *buf, uint buf_len) +/* + Read data for LOAD LOCAL INFILE + + SYNOPSIS + default_local_infile_read() + ptr Points to handle allocated by _init + buf Read data here + buf_len Ammount of data to read + + RETURN + > 0 number of bytes read + == 0 End of data + < 0 Error +*/ + +static int default_local_infile_read(void *ptr, char *buf, uint buf_len) { - default_local_infile_data *data = (default_local_infile_data *) ptr; + int count; + default_local_infile_data*data = (default_local_infile_data *) ptr; - return ((int) my_read(data->fd, (byte *)buf, buf_len, MYF(0))); + if ((count= (int) my_read(data->fd, (byte *) buf, buf_len, MYF(0))) < 0) + { + data->error_num= EE_READ; /* the errmsg for not entire file read */ + my_snprintf(data->error_msg, sizeof(data->error_msg)-1, + EE(EE_READ), + data->filename, my_errno); + } + return count; } -int -default_local_infile_end(void *ptr) +/* + Read data for LOAD LOCAL INFILE + + SYNOPSIS + default_local_infile_end() + ptr Points to handle allocated by _init + May be NULL if _init failed! + + RETURN +*/ + +static void default_local_infile_end(void *ptr) { - default_local_infile_data *data = (default_local_infile_data *) ptr; - if(data) + default_local_infile_data *data= (default_local_infile_data *) ptr; + if (data) /* If not error on open */ { - my_close(data->fd, MYF(0)); - my_free(ptr, MYF(0)); + if (data->fd >= 0) + my_close(data->fd, MYF(MY_WME)); + my_free(ptr, MYF(MY_WME)); } - return 0; } -int +/* + Return error from LOAD LOCAL INFILE + + SYNOPSIS + default_local_infile_end() + ptr Points to handle allocated by _init + May be NULL if _init failed! + error_msg Store error text here + error_msg_len Max lenght of error_msg + + RETURN + error message number +*/ + +static int default_local_infile_error(void *ptr, char *error_msg, uint error_msg_len) { - default_local_infile_data *data = (default_local_infile_data *) ptr; - - if(data) { + default_local_infile_data *data = (default_local_infile_data *) ptr; + if (data) /* If not error on open */ + { strmake(error_msg, data->error_msg, error_msg_len); return data->error_num; } - else - { - strmake(error_msg, "Internal error", error_msg_len); - return 0; - } + /* This can only happen if we got error on malloc of handle */ + strmov(error_msg, ER(CR_OUT_OF_MEMORY)); + return CR_OUT_OF_MEMORY; } -int +void mysql_set_local_infile_handler(MYSQL *mysql, - int (*local_infile_init)(void **, char *), + int (*local_infile_init)(void **, const char *), int (*local_infile_read)(void *, char *, uint), - int (*local_infile_end)(void *), + void (*local_infile_end)(void *), int (*local_infile_error)(void *, char *, uint)) { - if(mysql && - local_infile_init && - local_infile_read && - local_infile_end && - local_infile_error) { - mysql->options.local_infile_init= local_infile_init; - mysql->options.local_infile_read= local_infile_read; - mysql->options.local_infile_end= local_infile_end; - mysql->options.local_infile_error= local_infile_error; - return 0; - } - return 1; + mysql->options.local_infile_init= local_infile_init; + mysql->options.local_infile_read= local_infile_read; + mysql->options.local_infile_end= local_infile_end; + mysql->options.local_infile_error= local_infile_error; } -void -mysql_set_local_infile_default(MYSQL *mysql) +void mysql_set_local_infile_default(MYSQL *mysql) { mysql->options.local_infile_init= default_local_infile_init; mysql->options.local_infile_read= default_local_infile_read; |