diff --git a/include/mysys_err.h b/include/mysys_err.h index 2d23ead3..6ac5e2cc 100644 --- a/include/mysys_err.h +++ b/include/mysys_err.h @@ -22,38 +22,46 @@ extern "C" { #endif #define GLOB 0 /* Error maps */ -#define GLOBERRS 27 /* Max number of error messages in map's */ -#define EE(X) globerrs[ X ] /* Defines to add error to right map */ +#define GLOBERRS EE_LASTERROR - EE_FIRSTERROR + 1 /* Max number of error messages in map's */ +#define EE(X) globerrs[ (X) - EE_FIRSTERROR ] /* Defines to add error to right map */ extern const char * NEAR globerrs[]; /* my_error_messages is here */ -/* Error message numbers in global map */ -#define EE_FILENOTFOUND 0 -#define EE_CANTCREATEFILE 1 -#define EE_READ 2 -#define EE_WRITE 3 -#define EE_BADCLOSE 4 -#define EE_OUTOFMEMORY 5 -#define EE_DELETE 6 -#define EE_LINK 7 -#define EE_EOFERR 9 -#define EE_CANTLOCK 10 -#define EE_CANTUNLOCK 11 -#define EE_DIR 12 -#define EE_STAT 13 -#define EE_CANT_CHSIZE 14 -#define EE_CANT_OPEN_STREAM 15 -#define EE_GETWD 16 -#define EE_SETWD 17 -#define EE_LINK_WARNING 18 -#define EE_OPEN_WARNING 19 -#define EE_DISK_FULL 20 -#define EE_CANT_MKDIR 21 -#define EE_UNKNOWN_CHARSET 22 +/* Error message numbers in global map + +*/ +#define EE_FIRSTERROR 1 +#define EE_CANTCREATEFILE 1 +#define EE_READ 2 +#define EE_WRITE 3 +#define EE_BADCLOSE 4 +#define EE_OUTOFMEMORY 5 +#define EE_DELETE 6 +#define EE_LINK 7 +#define EE_EOFERR 9 +#define EE_CANTLOCK 10 +#define EE_CANTUNLOCK 11 +#define EE_DIR 12 +#define EE_STAT 13 +#define EE_CANT_CHSIZE 14 +#define EE_CANT_OPEN_STREAM 15 +#define EE_GETWD 16 +#define EE_SETWD 17 +#define EE_LINK_WARNING 18 +#define EE_OPEN_WARNING 19 +#define EE_DISK_FULL 20 +#define EE_CANT_MKDIR 21 +#define EE_UNKNOWN_CHARSET 22 #define EE_OUT_OF_FILERESOURCES 23 -#define EE_CANT_READLINK 24 -#define EE_CANT_SYMLINK 25 -#define EE_REALPATH 26 +#define EE_CANT_READLINK 24 +#define EE_CANT_SYMLINK 25 +#define EE_REALPATH 26 +#define EE_SYNC 27 +#define EE_UNKNOWN_COLLATION 28 +#define EE_FILENOTFOUND 29 +#define EE_FILE_NOT_CLOSED 30 +#define EE_CANT_CHMOD 31 +#define EE_LASTERROR 31 #ifdef __cplusplus } diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 21a38e7e..bf113ec7 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -44,14 +44,11 @@ mf_format.c mf_loadpath.c mf_pack.c mf_path.c -mf_tempfile.c mf_unixpath.c mf_wcomp.c mulalloc.c my_alloc.c my_compress.c -my_create.c -my_delete.c my_div.c my_error.c my_fopen.c diff --git a/libmariadb/errors.c b/libmariadb/errors.c index 77e52c2f..393f628b 100644 --- a/libmariadb/errors.c +++ b/libmariadb/errors.c @@ -22,7 +22,6 @@ const char * NEAR globerrs[GLOBERRS]= { - "File '%s' not found (Errcode: %d)", "Can't create/write to file '%s' (Errcode: %d)", "Error reading file '%s' (Errcode: %d)", "Error writing file '%s' (Errcode: %d)", @@ -41,14 +40,19 @@ const char * NEAR globerrs[GLOBERRS]= "Can't get working dirctory (Errcode: %d)", "Can't change dir to '%s' (Errcode: %d)", "Warning: '%s' had %d links", - "%d files and %d streams is left open\n", - "Disk is full writing '%s'. Waiting for someone to free space...", + "Warning: %d files and %d streams is left open\n", + "Disk is full writing '%s' (Errcode: %d). Waiting for someone to free space... (Expect up to %d secs delay for server to continue after freeing disk space)", "Can't create directory '%s' (Errcode: %d)", "Character set '%s' is not a compiled character set and is not specified in the '%s' file", "Out of resources when opening file '%s' (Errcode: %d)", "Can't read value for symlink '%s' (Error %d)", "Can't create symlink '%s' pointing at '%s' (Error %d)", "Error on realpath() on '%s' (Error %d)", + "Can't sync file '%s' to disk (Errcode: %d)", + "Collation '%s' is not a compiled collation and is not specified in the '%s' file", + "File '%s' not found (Errcode: %d)", + "File '%s' (fileno: %d) was not closed", + "Can't change mode for file '%s' to 0x%lx (Error: %d)" }; void init_glob_errs(void) diff --git a/libmariadb/mf_tempfile.c b/libmariadb/mf_tempfile.c deleted file mode 100644 index 46531108..00000000 --- a/libmariadb/mf_tempfile.c +++ /dev/null @@ -1,198 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -#include "mysys_priv.h" -#include -#include "my_static.h" -#include "mysys_err.h" -#include -#ifdef HAVE_PATHS_H -#include -#endif - -#ifdef HAVE_TEMPNAM -#if !defined( MSDOS) && !defined(OS2) -extern char **environ; -#endif -#endif - -/* - Create a temporary file in a given directory - This function should be used instead of my_tempnam() ! -*/ - -File create_temp_file(char *to, const char *dir, const char *prefix, - int mode __attribute__((unused)), - myf MyFlags __attribute__((unused))) -{ - File file= -1; - DBUG_ENTER("create_temp_file"); -#if defined(_MSC_VER) - { - char temp[FN_REFLEN],*end,*res,**old_env,*temp_env[1]; - old_env=environ; - if (dir) - { - end=strend(dir)-1; - if (!dir[0]) - { /* Change empty string to current dir */ - to[0]= FN_CURLIB; - to[1]= 0; - dir=to; - } - else if (*end == FN_DEVCHAR) - { /* Get current dir for drive */ - _fullpath(temp,dir,FN_REFLEN); - dir=to; - } - else if (*end == FN_LIBCHAR && dir < end && end[-1] != FN_DEVCHAR) - { - strmake(to,dir,(uint) (end-dir)); /* Copy and remove last '\' */ - dir=to; - } - environ=temp_env; /* Force use of dir (dir not checked) */ - temp_env[0]=0; - } - if ((res=tempnam((char*) dir,(char *) prefix))) - { - strmake(to,res,FN_REFLEN-1); - (*free)(res); - file=my_create(to,0, mode, MyFlags); - } - environ=old_env; - } -#elif defined(_ZTC__) - if (!dir) - dir=getenv("TMPDIR"); - if ((res=tempnam((char*) dir,(char *) prefix))) - { - strmake(to,res,FN_REFLEN-1); - (*free)(res); - file=my_create(to, 0, mode, MyFlags); - } -#elif defined(HAVE_MKSTEMP) - { - char prefix_buff[30]; - uint pfx_len; - File org_file; - - pfx_len=(strmov(strnmov(prefix_buff, - prefix ? prefix : "tmp.", - sizeof(prefix_buff)-7),"XXXXXX") - prefix_buff); - if (!dir && ! (dir =getenv("TMPDIR"))) - dir=P_tmpdir; - if (strlen(dir)+ pfx_len > FN_REFLEN-2) - { - errno=my_errno= ENAMETOOLONG; - return 1; - } - strmov(to,dir); - strmov(convert_dirname(to),prefix_buff); - org_file=mkstemp(to); - file=my_register_filename(org_file, to, FILE_BY_MKSTEMP, - EE_CANTCREATEFILE, MyFlags); - /* If we didn't manage to register the name, remove the temp file */ - if (org_file >= 0 && file < 0) - { - int tmp=my_errno; - (void) my_delete(to, MYF(MY_WME | ME_NOINPUT)); - my_errno=tmp; - } - } -#elif defined(HAVE_TEMPNAM) - { - char *res,**old_env,*temp_env[1]; - if (dir && !dir[0]) - { /* Change empty string to current dir */ - to[0]= FN_CURLIB; - to[1]= 0; - dir=to; - } -#ifdef OS2 - // changing environ variable doesn't work with VACPP - char buffer[256]; - sprintf( buffer, "TMP=%s", dir); - // remove ending backslash - if (buffer[strlen(buffer)-1] == '\\') - buffer[strlen(buffer)-1] = '\0'; - putenv( buffer); -#else - old_env= (char**) environ; - if (dir) - { /* Don't use TMPDIR if dir is given */ - environ=(const char**) temp_env; - temp_env[0]=0; - } -#endif - if ((res=tempnam((char*) dir, (char*) prefix))) - { - strmake(to,res,FN_REFLEN-1); - (*free)(res); - file=my_create(to,0, - (int) (O_RDWR | O_BINARY | O_TRUNC | - O_TEMPORARY | O_SHORT_LIVED), - MYF(MY_WME)); - - } - else - { - DBUG_PRINT("error",("Got error: %d from tempnam",errno)); - } -#ifndef OS2 - environ=(const char**) old_env; -#endif - } -#else - { - register long uniq; - register int length; - my_string pos,end_pos; - /* Make an unique number */ - pthread_mutex_lock(&THR_LOCK_open); - uniq= ((long) getpid() << 20) + (long) _my_tempnam_used++ ; - pthread_mutex_unlock(&THR_LOCK_open); - if (!dir && !(dir=getenv("TMPDIR"))) /* Use this if possibly */ - dir=P_tmpdir; /* Use system default */ - length=strlen(dir)+strlen(pfx)+1; - - DBUG_PRINT("test",("mallocing %d byte",length+8+sizeof(TMP_EXT)+1)); - if (length+8+sizeof(TMP_EXT)+1 > FN_REFLENGTH) - errno=my_errno= ENAMETOOLONG; - else - { - end_pos=strmov(to,dir); - if (end_pos != to && end_pos[-1] != FN_LIBCHAR) - *end_pos++=FN_LIBCHAR; - end_pos=strmov(end_pos,pfx); - - for (length=0 ; length < 8 && uniq ; length++) - { - *end_pos++= _dig_vec[(int) (uniq & 31)]; - uniq >>= 5; - } - (void) strmov(end_pos,TMP_EXT); - file=my_create(to,0, - (int) (O_RDWR | O_BINARY | O_TRUNC | - O_TEMPORARY | O_SHORT_LIVED), - MYF(MY_WME)); - } - } -#endif - if (file >= 0) - thread_safe_increment(my_tmp_file_created,&THR_LOCK_open); - DBUG_RETURN(file); -} diff --git a/libmariadb/my_create.c b/libmariadb/my_create.c deleted file mode 100644 index fe455583..00000000 --- a/libmariadb/my_create.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -#define USES_TYPES -#include "mysys_priv.h" -#include -#include "mysys_err.h" -#include -#if defined(MSDOS) || defined(_WIN32) || defined(__EMX__) || defined(OS2) -#include -#endif - - /* - ** Create a new file - ** Arguments: - ** Path-name of file - ** Read | write on file (umask value) - ** Read & Write on open file - ** Special flags - */ - - -File my_create(const char *FileName, int CreateFlags, int access_flags, - myf MyFlags) -{ - int fd; - DBUG_ENTER("my_create"); - DBUG_PRINT("my",("Name: '%s' CreateFlags: %d AccessFlags: %d MyFlags: %d", - FileName, CreateFlags, access_flags, MyFlags)); - -#if !defined(NO_OPEN_3) && !defined(__EMX__) - fd = open((my_string) FileName, access_flags | O_CREAT, - CreateFlags ? CreateFlags : my_umask); -#elif defined(VMS) - fd = open((my_string) FileName, access_flags | O_CREAT, 0, - "ctx=stm","ctx=bin"); -#elif defined(MSDOS) || defined(_WIN32) || defined(__EMX__) || defined(OS2) - if (access_flags & O_SHARE) - fd = sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY, - SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); - else - fd = open((my_string) FileName, access_flags | O_CREAT | O_BINARY, - MY_S_IREAD | MY_S_IWRITE); -#else - fd = open(FileName, access_flags); -#endif - - DBUG_RETURN(my_register_filename(fd, FileName, FILE_BY_CREATE, - EE_CANTCREATEFILE, MyFlags)); -} /* my_create */ diff --git a/libmariadb/my_delete.c b/libmariadb/my_delete.c deleted file mode 100644 index 77d5f311..00000000 --- a/libmariadb/my_delete.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -#include "mysys_priv.h" - -#include "mysys_err.h" - -int my_delete(const char *name, myf MyFlags) -{ - int err; - DBUG_ENTER("my_delete"); - DBUG_PRINT("my",("name %s MyFlags %d", name, MyFlags)); - - if ((err = unlink(name)) == -1) - { - my_errno=errno; - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_DELETE,MYF(ME_BELL+ME_WAITTANG+(MyFlags & ME_NOINPUT)), - name,errno); - } - DBUG_RETURN(err); -} /* my_delete */ diff --git a/libmariadb/my_loaddata.c b/libmariadb/my_loaddata.c index fd279121..38b5b47e 100644 --- a/libmariadb/my_loaddata.c +++ b/libmariadb/my_loaddata.c @@ -47,6 +47,9 @@ #include "errmsg.h" #include "mysql.h" #include +#ifdef _WIN32 +#include +#endif typedef struct st_mysql_infile_info { @@ -61,7 +64,12 @@ static int mysql_local_infile_init(void **ptr, const char *filename, void *userdata) { MYSQL_INFILE_INFO *info; - + int CodePage= -1; +#ifdef _WIN32 + MYSQL *mysql= (MYSQL *)userdata; + wchar_t *w_filename= NULL; + int Length; +#endif DBUG_ENTER("mysql_local_infile_init"); info = (MYSQL_INFILE_INFO *)my_malloc(sizeof(MYSQL_INFILE_INFO), MYF(MY_ZEROFILL)); @@ -72,7 +80,47 @@ int mysql_local_infile_init(void **ptr, const char *filename, void *userdata) *ptr = info; info->filename = filename; - info->fd = my_open(info->filename, O_RDONLY, MYF(0)); + +#ifdef _WIN32 + if (mysql) + CodePage= madb_get_windows_cp(mysql->charset->csname); +#endif + if (CodePage == -1) + { +#ifdef _WIN32 + info->fd= sopen(info->filename, _O_RDONLY, _SH_DENYNO , _S_IREAD | _S_IWRITE); +#else + info->fd = open(info->filename, O_RDONLY | O_BINARY, my_umask); +#endif + my_errno= errno; + } +#ifdef _WIN32 + else + { + if ((Length= MultiByteToWideChar(CodePage, 0, info->filename, strlen(info->filename), NULL, 0))) + { + if (!(w_filename= (wchar_t *)my_malloc((Length + 1) * sizeof(wchar_t), MYF(MY_ZEROFILL)))) + { + info->error_no= CR_OUT_OF_MEMORY; + my_snprintf((char *)info->error_msg, sizeof(info->error_msg), + ER(CR_OUT_OF_MEMORY)); + DBUG_RETURN(1); + } + Length= MultiByteToWideChar(CodePage, 0, info->filename, strlen(info->filename), w_filename, Length); + } + if (Length == 0) + { + my_free((gptr)w_filename, MYF(0)); + info->error_no= CR_UNKNOWN_ERROR; + my_snprintf((char *)info->error_msg, sizeof(info->error_msg), + "Character conversion error: %d", GetLastError()); + DBUG_RETURN(1); + } + info->fd= _wsopen(w_filename, _O_RDONLY, _SH_DENYNO , _S_IREAD | _S_IWRITE); + my_errno= errno; + my_free((gptr)w_filename, MYF(0)); + } +#endif if (info->fd < 0) { @@ -95,7 +143,7 @@ int mysql_local_infile_read(void *ptr, char * buf, unsigned int buf_len) DBUG_ENTER("mysql_local_infile_read"); - count= my_read(info->fd, buf, buf_len, MYF(0)); + count= read(info->fd, (void *)buf, (size_t)buf_len); if (count < 0) { @@ -137,8 +185,8 @@ void mysql_local_infile_end(void *ptr) if (info) { if (info->fd >= 0) - my_close(info->fd, MYF(0)); - my_free(ptr, MYF(0)); + close(info->fd); + my_free((gptr)ptr, MYF(0)); } DBUG_VOID_RETURN; } @@ -197,8 +245,10 @@ my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename) /* check if all callback functions exist */ if (!conn->options.local_infile_init || !conn->options.local_infile_end || !conn->options.local_infile_read || !conn->options.local_infile_error) + { + conn->options.local_infile_userdata= conn; mysql_set_local_infile_default(conn); - + } /* allocate buffer for reading data */ buf = (uchar *)my_malloc(buflen, MYF(0)); @@ -250,3 +300,4 @@ infile_error: DBUG_RETURN(result); } /* }}} */ + diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index 0de29c90..5fbc3d87 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -799,7 +799,7 @@ static int test_bug49694(MYSQL *mysql) fprintf (fp, "%.08d,%d,%f\r\n", 100 + i, i % 3 + 1, 60000.0 + i/100); fclose(fp); - rc= mysql_query(mysql, "LOAD DATA LOCAL INFILE './data.csv' INTO TABLE enclist " + rc= mysql_query(mysql, "LOAD DATA LOCAL INFILE 'data.csv' INTO TABLE enclist " "FIELDS TERMINATED BY '.' LINES TERMINATED BY '\r\n'"); check_mysql_rc(rc, mysql); @@ -838,6 +838,52 @@ static int test_ldi_path(MYSQL *mysql) return OK; } +#if _WIN32 +static int test_conc44(MYSQL *mysql) +{ + char query[1024]; + char *a_filename= "æøå.csv"; + int rc; + int i; + FILE *fp; + + rc= mysql_set_character_set(mysql, "latin1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS enclist"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE `enclist` (" + " `pat_id` int(11) NOT NULL," + " `episode_id` int(11) NOT NULL," + " `enc_id` double NOT NULL," + " PRIMARY KEY (`pat_id`,`episode_id`,`enc_id`)" + ") ENGINE=MyISAM DEFAULT CHARSET=latin1"); + check_mysql_rc(rc, mysql); + + fp= fopen(a_filename, "w"); + FAIL_IF(!fp, "Can't open file"); + + for (i=0; i < 100; i++) + fprintf (fp, "%.08d,%d,%f\r\n", 100 + i, i % 3 + 1, 60000.0 + i/100); + fclose(fp); + + sprintf(query, "LOAD DATA LOCAL INFILE '%s' INTO TABLE enclist " + "FIELDS TERMINATED BY '.' LINES TERMINATED BY '\r\n'", a_filename); + rc= mysql_query(mysql, query); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "DELETE FROM enclist"); + check_mysql_rc(rc, mysql); + + FAIL_IF(mysql_affected_rows(mysql) != 100, "Import failure. Expected 2 imported rows"); + + rc= mysql_query(mysql, "DROP TABLE enclist"); + check_mysql_rc(rc, mysql); + return OK; +} +#endif + struct my_tests_st my_tests[] = { {"test_bug28075", test_bug28075, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_bug28505", test_bug28505, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, @@ -853,6 +899,9 @@ struct my_tests_st my_tests[] = { {"test_wl4284_1", test_wl4284_1, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_bug49694", test_bug49694, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_ldi_path", test_ldi_path, TEST_CONNECTION_NEW, 0, NULL, NULL}, +#ifdef _WIN32 + {"test_conc44", test_conc44, TEST_CONNECTION_NEW, 0, NULL, NULL}, +#endif {NULL, NULL, 0, 0, NULL, 0} };