summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@montyprogram.com>2011-06-12 15:52:07 +0200
committerVladislav Vaintroub <wlad@montyprogram.com>2011-06-12 15:52:07 +0200
commit4171483b539555f50336d4304d931ef743cf7011 (patch)
treefe7d215b1d77b11bf630479aab5bbb71e63b050c /mysys
parent824ce5f3eae52ee418665211c24218a5772c43f2 (diff)
downloadmariadb-git-4171483b539555f50336d4304d931ef743cf7011.tar.gz
Backport Fix for Bug#24509 - 2048 file descriptor limit on windows needs increasing.
The patch replaces the use of the POSIX I/O interfaces in mysys on Windows with the Win32 API calls (CreateFile, WriteFile, etc). The Windows HANDLE for the open file is stored in the my_file_info struct, along with a flag for append mode (because the Windows API does not support opening files in append mode in all cases) The default max open files has been increased to 16384 and can be increased further by setting --max-open-files=<value> during the server start. Noteworthy benefit of this patch is that it removes limits from the table_cache size - allowing for more simultaneus users
Diffstat (limited to 'mysys')
-rw-r--r--mysys/CMakeLists.txt2
-rw-r--r--mysys/default_modify.c8
-rw-r--r--mysys/mf_iocache.c3
-rw-r--r--mysys/my_chsize.c19
-rw-r--r--mysys/my_create.c15
-rw-r--r--mysys/my_dup.c6
-rw-r--r--mysys/my_file.c1
-rw-r--r--mysys/my_fopen.c48
-rw-r--r--mysys/my_fstream.c17
-rw-r--r--mysys/my_init.c3
-rw-r--r--mysys/my_lib.c26
-rw-r--r--mysys/my_lock.c137
-rw-r--r--mysys/my_mmap.c6
-rw-r--r--mysys/my_open.c227
-rw-r--r--mysys/my_pread.c81
-rw-r--r--mysys/my_quick.c22
-rw-r--r--mysys/my_read.c7
-rw-r--r--mysys/my_seek.c17
-rw-r--r--mysys/my_static.c2
-rw-r--r--mysys/my_sync.c2
-rw-r--r--mysys/my_winerr.c123
-rw-r--r--mysys/my_winfile.c681
-rw-r--r--mysys/my_write.c36
-rw-r--r--mysys/mysys_priv.h24
24 files changed, 1122 insertions, 391 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index 9ab19222caf..0cf10e6e993 100644
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -38,7 +38,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_
my_mkdir.c my_mmap.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c
my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_sleep.c
my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c
- my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c stacktrace.c
+ my_winerr.c my_winfile.c my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c stacktrace.c
rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c
thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c my_getpagesize.c
lf_alloc-pin.c lf_dynarray.c lf_hash.c
diff --git a/mysys/default_modify.c b/mysys/default_modify.c
index 88df0122da2..ccbf47176a6 100644
--- a/mysys/default_modify.c
+++ b/mysys/default_modify.c
@@ -21,7 +21,7 @@
#define BUFF_SIZE 1024
#define RESERVE 1024 /* Extend buffer with this extent */
-#ifdef __WIN__
+#ifdef _WIN32
#define NEWLINE "\r\n"
#define NEWLINE_LEN 2
#else
@@ -78,7 +78,7 @@ int modify_defaults_file(const char *file_location, const char *option,
DBUG_RETURN(2);
/* my_fstat doesn't use the flag parameter */
- if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
+ if (my_fstat(my_fileno(cnf_file), &file_stat, MYF(0)))
goto malloc_err;
if (option && option_value)
@@ -96,7 +96,7 @@ int modify_defaults_file(const char *file_location, const char *option,
NEWLINE_LEN + /* Space for newline */
RESERVE); /* Some additional space */
- buffer_size= (file_stat.st_size +
+ buffer_size= (uint)(file_stat.st_size +
1); /* The ending zero */
/*
@@ -213,7 +213,7 @@ int modify_defaults_file(const char *file_location, const char *option,
if (opt_applied)
{
/* Don't write the file if there are no changes to be made */
- if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
+ if (my_chsize(my_fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
MYF(MY_WME)) ||
my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
my_fwrite(cnf_file, (uchar*) file_buffer, (size_t) (dst_ptr - file_buffer),
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index 3824669365f..1905437cc0a 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -1659,9 +1659,6 @@ int my_block_write(register IO_CACHE *info, const uchar *Buffer, size_t Count,
Buffer+=length;
pos+= length;
Count-= length;
-#ifndef HAVE_PREAD
- info->seek_not_done=1;
-#endif
}
/* Check if we want to write inside the used part of the buffer.*/
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index b1dbb22c687..b9013811b34 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -52,20 +52,13 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
if (oldsize > newlength)
{
-#if defined(HAVE_SETFILEPOINTER)
- /* This is for the moment only true on windows */
- long is_success;
- HANDLE win_file= (HANDLE) _get_osfhandle(fd);
- long length_low, length_high;
- length_low= (long) (ulong) newlength;
- length_high= (long) ((ulonglong) newlength >> 32);
- is_success= SetFilePointer(win_file, length_low, &length_high, FILE_BEGIN);
- if (is_success == -1 && (my_errno= GetLastError()) != NO_ERROR)
+#ifdef _WIN32
+ if (my_win_chsize(fd, newlength))
+ {
+ my_errno= errno;
goto err;
- if (SetEndOfFile(win_file))
- DBUG_RETURN(0);
- my_errno= GetLastError();
- goto err;
+ }
+ DBUG_RETURN(0);
#elif defined(HAVE_FTRUNCATE)
if (ftruncate(fd, (off_t) newlength))
{
diff --git a/mysys/my_create.c b/mysys/my_create.c
index 5c9a1e027d2..d0436276d03 100644
--- a/mysys/my_create.c
+++ b/mysys/my_create.c
@@ -18,7 +18,7 @@
#include "mysys_err.h"
#include <errno.h>
#include <my_sys.h>
-#if defined(__WIN__)
+#if defined(_WIN32)
#include <share.h>
#endif
@@ -41,16 +41,12 @@ File my_create(const char *FileName, int CreateFlags, int access_flags,
FileName, CreateFlags, access_flags, MyFlags));
#if !defined(NO_OPEN_3)
- fd = open((char *) FileName, access_flags | O_CREAT,
+ fd= open((char *) FileName, access_flags | O_CREAT,
CreateFlags ? CreateFlags : my_umask);
-#elif defined(VMS)
- fd = open((char *) FileName, access_flags | O_CREAT, 0,
- "ctx=stm","ctx=bin");
-#elif defined(__WIN__)
- fd= my_sopen((char *) FileName, access_flags | O_CREAT | O_BINARY,
- SH_DENYNO, MY_S_IREAD | MY_S_IWRITE);
+#elif defined(_WIN32)
+ fd= my_win_open(FileName, access_flags | O_CREAT);
#else
- fd = open(FileName, access_flags);
+ fd= open(FileName, access_flags);
#endif
if ((MyFlags & MY_SYNC_DIR) && (fd >=0) &&
@@ -71,6 +67,7 @@ File my_create(const char *FileName, int CreateFlags, int access_flags,
if (unlikely(fd >= 0 && rc < 0))
{
int tmp= my_errno;
+ my_close(fd, MyFlags);
my_delete(FileName, MyFlags);
my_errno= tmp;
}
diff --git a/mysys/my_dup.c b/mysys/my_dup.c
index 55f5e0c0099..5fdd6e9f364 100644
--- a/mysys/my_dup.c
+++ b/mysys/my_dup.c
@@ -29,7 +29,11 @@ File my_dup(File file, myf MyFlags)
const char *filename;
DBUG_ENTER("my_dup");
DBUG_PRINT("my",("file: %d MyFlags: %d", file, MyFlags));
- fd = dup(file);
+#ifdef _WIN32
+ fd= my_win_dup(file);
+#else
+ fd= dup(file);
+#endif
filename= (((uint) file < my_file_limit) ?
my_file_info[(int) file].name : "Unknown");
DBUG_RETURN(my_register_filename(fd, filename, FILE_BY_DUP,
diff --git a/mysys/my_file.c b/mysys/my_file.c
index 594f361437f..d8d51b91ab2 100644
--- a/mysys/my_file.c
+++ b/mysys/my_file.c
@@ -97,6 +97,7 @@ uint my_set_max_open_files(uint files)
DBUG_ENTER("my_set_max_open_files");
DBUG_PRINT("enter",("files: %u my_file_limit: %u", files, my_file_limit));
+ files+= MY_FILE_MIN;
files= set_max_open_files(min(files, OS_FILE_LIMIT));
if (files <= MY_NFILE)
DBUG_RETURN(files);
diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index a4b0c9f895d..ae631a59353 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -46,24 +46,14 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags)
DBUG_ENTER("my_fopen");
DBUG_PRINT("my",("Name: '%s' flags: %d MyFlags: %d",
filename, flags, MyFlags));
- /*
- if we are not creating, then we need to use my_access to make sure
- the file exists since Windows doesn't handle files like "com1.sym"
- very well
- */
-#ifdef __WIN__
- if (check_if_legal_filename(filename))
- {
- errno= EACCES;
- fd= 0;
- }
- else
+
+ make_ftype(type,flags);
+
+#ifdef _WIN32
+ fd= my_win_fopen(filename, type);
+#else
+ fd= fopen(filename, type);
#endif
- {
- make_ftype(type,flags);
- fd = fopen(filename, type);
- }
-
if (fd != 0)
{
/*
@@ -71,18 +61,20 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags)
on some OS (SUNOS). Actually the filename save isn't that important
so we can ignore if this doesn't work.
*/
- if ((uint) fileno(fd) >= my_file_limit)
+
+ int filedesc= my_fileno(fd);
+ if ((uint)filedesc >= my_file_limit)
{
thread_safe_increment(my_stream_opened,&THR_LOCK_open);
DBUG_RETURN(fd); /* safeguard */
}
pthread_mutex_lock(&THR_LOCK_open);
- if ((my_file_info[fileno(fd)].name = (char*)
+ if ((my_file_info[filedesc].name= (char*)
my_strdup(filename,MyFlags)))
{
my_stream_opened++;
my_file_total_opened++;
- my_file_info[fileno(fd)].type = STREAM_BY_FOPEN;
+ my_file_info[filedesc].type= STREAM_BY_FOPEN;
pthread_mutex_unlock(&THR_LOCK_open);
DBUG_PRINT("exit",("stream: 0x%lx", (long) fd));
DBUG_RETURN(fd);
@@ -240,8 +232,13 @@ int my_fclose(FILE *fd, myf MyFlags)
DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) fd, MyFlags));
pthread_mutex_lock(&THR_LOCK_open);
- file=fileno(fd);
- if ((err = fclose(fd)) < 0)
+ file= my_fileno(fd);
+#ifndef _WIN32
+ err= fclose(fd);
+#else
+ err= my_win_fclose(fd);
+#endif
+ if(err < 0)
{
my_errno=errno;
if (MyFlags & (MY_FAE | MY_WME))
@@ -272,7 +269,12 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags)
Filedes, Flags, MyFlags));
make_ftype(type,Flags);
- if ((fd = fdopen(Filedes, type)) == 0)
+#ifdef _WIN32
+ fd= my_win_fdopen(Filedes, type);
+#else
+ fd= fdopen(Filedes, type);
+#endif
+ if (!fd)
{
my_errno=errno;
if (MyFlags & (MY_FAE | MY_WME))
diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c
index f3b5418b906..2059e1a9f18 100644
--- a/mysys/my_fstream.c
+++ b/mysys/my_fstream.c
@@ -56,11 +56,11 @@ size_t my_fread(FILE *stream, uchar *Buffer, size_t Count, myf MyFlags)
{
if (ferror(stream))
my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
- my_filename(fileno(stream)),errno);
+ my_filename(my_fileno(stream)),errno);
else
if (MyFlags & (MY_NABP | MY_FNABP))
my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
- my_filename(fileno(stream)),errno);
+ my_filename(my_fileno(stream)),errno);
}
my_errno=errno ? errno : -1;
if (ferror(stream) || MyFlags & (MY_NABP | MY_FNABP))
@@ -142,7 +142,7 @@ size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags)
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG),
- my_filename(fileno(stream)),errno);
+ my_filename(my_fileno(stream)),errno);
}
writtenbytes= (size_t) -1; /* Return that we got error */
break;
@@ -182,3 +182,14 @@ my_off_t my_ftell(FILE *stream, myf MyFlags __attribute__((unused)))
DBUG_PRINT("exit",("ftell: %lu",(ulong) pos));
DBUG_RETURN((my_off_t) pos);
} /* my_ftell */
+
+
+/* Get a File corresponding to the stream*/
+int my_fileno(FILE *f)
+{
+#ifdef _WIN32
+ return my_win_fileno(f);
+#else
+ return fileno(f);
+#endif
+}
diff --git a/mysys/my_init.c b/mysys/my_init.c
index e7ab9ba7a1f..7f174cea1f0 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -274,6 +274,7 @@ void my_parameter_handler(const wchar_t * expression, const wchar_t * function,
{
DBUG_PRINT("my",("Expression: %s function: %s file: %s, line: %d",
expression, function, file, line));
+ __debugbreak();
}
@@ -298,7 +299,7 @@ int handle_rtc_failure(int err_type, const char *file, int line,
fprintf(stderr, " At %s:%d\n", file, line);
va_end(args);
(void) fflush(stderr);
-
+ __debugbreak();
return 0; /* Error is handled */
}
#pragma runtime_checks("", restore)
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index c18d14fb549..033f8789b49 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -35,8 +35,7 @@
# if defined(HAVE_NDIR_H)
# include <ndir.h>
# endif
-# if defined(__WIN__)
-# include <dos.h>
+# if defined(_WIN32)
# ifdef __BORLANDC__
# include <dir.h>
# endif
@@ -92,7 +91,7 @@ static int comp_names(struct fileinfo *a, struct fileinfo *b)
} /* comp_names */
-#if !defined(__WIN__)
+#if !defined(_WIN32)
MY_DIR *my_dir(const char *path, myf MyFlags)
{
@@ -507,19 +506,24 @@ error:
DBUG_RETURN((MY_DIR *) NULL);
} /* my_dir */
-#endif /* __WIN__ */
+#endif /* _WIN32 */
/****************************************************************************
** File status
** Note that MY_STAT is assumed to be same as struct stat
****************************************************************************/
-int my_fstat(int Filedes, MY_STAT *stat_area,
+
+int my_fstat(File Filedes, MY_STAT *stat_area,
myf MyFlags __attribute__((unused)))
{
DBUG_ENTER("my_fstat");
DBUG_PRINT("my",("fd: %d MyFlags: %d", Filedes, MyFlags));
+#ifdef _WIN32
+ DBUG_RETURN(my_win_fstat(Filedes, stat_area));
+#else
DBUG_RETURN(fstat(Filedes, (struct stat *) stat_area));
+#endif
}
@@ -531,11 +535,15 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags)
(long) stat_area, my_flags));
if ((m_used= (stat_area == NULL)))
- if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
+ if (!(stat_area= (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
goto error;
- if (! stat((char *) path, (struct stat *) stat_area) )
- DBUG_RETURN(stat_area);
-
+#ifndef _WIN32
+ if (! stat((char *) path, (struct stat *) stat_area) )
+ DBUG_RETURN(stat_area);
+#else
+ if (! my_win_stat(path, stat_area) )
+ DBUG_RETURN(stat_area);
+#endif
DBUG_PRINT("error",("Got errno: %d from stat", errno));
my_errno= errno;
if (m_used) /* Free if new area */
diff --git a/mysys/my_lock.c b/mysys/my_lock.c
index 8450fcfc30a..6bbb177e4b6 100644
--- a/mysys/my_lock.c
+++ b/mysys/my_lock.c
@@ -22,13 +22,113 @@
#undef NO_ALARM_LOOP
#endif
#include <my_alarm.h>
-#ifdef __WIN__
-#include <sys/locking.h>
-#endif
#ifdef __NETWARE__
#include <nks/fsio.h>
#endif
+#ifdef _WIN32
+#define WIN_LOCK_INFINITE -1
+#define WIN_LOCK_SLEEP_MILLIS 100
+
+static int win_lock(File fd, int locktype, my_off_t start, my_off_t length,
+ int timeout_sec)
+{
+ LARGE_INTEGER liOffset,liLength;
+ DWORD dwFlags;
+ OVERLAPPED ov= {0};
+ HANDLE hFile= (HANDLE)my_get_osfhandle(fd);
+ DWORD lastError= 0;
+ int i;
+ int timeout_millis= timeout_sec * 1000;
+
+ DBUG_ENTER("win_lock");
+
+ liOffset.QuadPart= start;
+ liLength.QuadPart= length;
+
+ ov.Offset= liOffset.LowPart;
+ ov.OffsetHigh= liOffset.HighPart;
+
+ if (locktype == F_UNLCK)
+ {
+ if (UnlockFileEx(hFile, 0, liLength.LowPart, liLength.HighPart, &ov))
+ DBUG_RETURN(0);
+ /*
+ For compatibility with fcntl implementation, ignore error,
+ if region was not locked
+ */
+ if (GetLastError() == ERROR_NOT_LOCKED)
+ {
+ SetLastError(0);
+ DBUG_RETURN(0);
+ }
+ goto error;
+ }
+ else if (locktype == F_RDLCK)
+ /* read lock is mapped to a shared lock. */
+ dwFlags= 0;
+ else
+ /* write lock is mapped to an exclusive lock. */
+ dwFlags= LOCKFILE_EXCLUSIVE_LOCK;
+
+ /*
+ Drop old lock first to avoid double locking.
+ During analyze of Bug#38133 (Myisamlog test fails on Windows)
+ I met the situation that the program myisamlog locked the file
+ exclusively, then additionally shared, then did one unlock, and
+ then blocked on an attempt to lock it exclusively again.
+ Unlocking before every lock fixed the problem.
+ Note that this introduces a race condition. When the application
+ wants to convert an exclusive lock into a shared one, it will now
+ first unlock the file and then lock it shared. A waiting exclusive
+ lock could step in here. For reasons described in Bug#38133 and
+ Bug#41124 (Server hangs on Windows with --external-locking after
+ INSERT...SELECT) and in the review thread at
+ http://lists.mysql.com/commits/60721 it seems to be the better
+ option than not to unlock here.
+ If one day someone notices a way how to do file lock type changes
+ on Windows without unlocking before taking the new lock, please
+ change this code accordingly to fix the race condition.
+ */
+ if (!UnlockFileEx(hFile, 0, liLength.LowPart, liLength.HighPart, &ov) &&
+ (GetLastError() != ERROR_NOT_LOCKED))
+ goto error;
+
+ if (timeout_sec == WIN_LOCK_INFINITE)
+ {
+ if (LockFileEx(hFile, dwFlags, 0, liLength.LowPart, liLength.HighPart, &ov))
+ DBUG_RETURN(0);
+ goto error;
+ }
+
+ dwFlags|= LOCKFILE_FAIL_IMMEDIATELY;
+ timeout_millis= timeout_sec * 1000;
+ /* Try lock in a loop, until the lock is acquired or timeout happens */
+ for(i= 0; ;i+= WIN_LOCK_SLEEP_MILLIS)
+ {
+ if (LockFileEx(hFile, dwFlags, 0, liLength.LowPart, liLength.HighPart, &ov))
+ DBUG_RETURN(0);
+
+ if (GetLastError() != ERROR_LOCK_VIOLATION)
+ goto error;
+
+ if (i >= timeout_millis)
+ break;
+ Sleep(WIN_LOCK_SLEEP_MILLIS);
+ }
+
+ /* timeout */
+ errno= EAGAIN;
+ DBUG_RETURN(-1);
+
+error:
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+}
+#endif
+
+
+
/*
Lock a part of a file
@@ -97,29 +197,16 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length,
DBUG_RETURN(0);
}
}
-#elif defined(HAVE_LOCKING)
- /* Windows */
+#elif defined(_WIN32)
{
- my_bool error= FALSE;
- pthread_mutex_lock(&my_file_info[fd].mutex);
- if (MyFlags & MY_SEEK_NOT_DONE)
- {
- if( my_seek(fd,start,MY_SEEK_SET,MYF(MyFlags & ~MY_SEEK_NOT_DONE))
- == MY_FILEPOS_ERROR )
- {
- /*
- If my_seek fails my_errno will already contain an error code;
- just unlock and return error code.
- */
- DBUG_PRINT("error",("my_errno: %d (%d)",my_errno,errno));
- pthread_mutex_unlock(&my_file_info[fd].mutex);
- DBUG_RETURN(-1);
- }
- }
- error= locking(fd,locktype,(ulong) length) && errno != EINVAL;
- pthread_mutex_unlock(&my_file_info[fd].mutex);
- if (!error)
- DBUG_RETURN(0);
+ int timeout_sec;
+ if (MyFlags & MY_NO_WAIT)
+ timeout_sec= 0;
+ else
+ timeout_sec= WIN_LOCK_INFINITE;
+
+ if(win_lock(fd, locktype, start, length, timeout_sec) == 0)
+ DBUG_RETURN(0);
}
#else
#if defined(HAVE_FCNTL)
diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c
index 023a06fd896..303d8efaf30 100644
--- a/mysys/my_mmap.c
+++ b/mysys/my_mmap.c
@@ -27,17 +27,17 @@ int my_msync(int fd, void *addr, size_t len, int flags)
return my_sync(fd, MYF(0));
}
-#elif defined(__WIN__)
+#elif defined(_WIN32)
static SECURITY_ATTRIBUTES mmap_security_attributes=
{sizeof(SECURITY_ATTRIBUTES), 0, TRUE};
void *my_mmap(void *addr, size_t len, int prot,
- int flags, int fd, my_off_t offset)
+ int flags, File fd, my_off_t offset)
{
HANDLE hFileMap;
LPVOID ptr;
- HANDLE hFile= (HANDLE)_get_osfhandle(fd);
+ HANDLE hFile= (HANDLE)my_get_osfhandle(fd);
if (hFile == INVALID_HANDLE_VALUE)
return MAP_FAILED;
diff --git a/mysys/my_open.c b/mysys/my_open.c
index fe7f65c450b..b1788506832 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -17,9 +17,7 @@
#include "mysys_err.h"
#include <my_dir.h>
#include <errno.h>
-#if defined(__WIN__)
-#include <share.h>
-#endif
+
/*
Open a file
@@ -43,29 +41,8 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
DBUG_ENTER("my_open");
DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d",
FileName, Flags, MyFlags));
-#if defined(__WIN__)
- /*
- Check that we don't try to open or create a file name that may
- cause problems for us in the future (like PRN)
- */
- if (check_if_legal_filename(FileName))
- {
- errno= EACCES;
- DBUG_RETURN(my_register_filename(-1, FileName, FILE_BY_OPEN,
- EE_FILENOTFOUND, MyFlags));
- }
-#ifndef __WIN__
- if (Flags & O_SHARE)
- fd = sopen((char *) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO,
- MY_S_IREAD | MY_S_IWRITE);
- else
- fd = open((char *) FileName, Flags | O_BINARY,
- MY_S_IREAD | MY_S_IWRITE);
-#else
- fd= my_sopen((char *) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO,
- MY_S_IREAD | MY_S_IWRITE);
-#endif
-
+#if defined(_WIN32)
+ fd= my_win_open(FileName, Flags);
#elif !defined(NO_OPEN_3)
fd = open(FileName, Flags, my_umask); /* Normal unix */
#else
@@ -94,11 +71,14 @@ int my_close(File fd, myf MyFlags)
DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags));
pthread_mutex_lock(&THR_LOCK_open);
+#ifndef _WIN32
do
{
err= close(fd);
} while (err == -1 && errno == EINTR);
-
+#else
+ err= my_win_close(fd);
+#endif
if (err)
{
DBUG_PRINT("error",("Got error %d on close",err));
@@ -109,9 +89,6 @@ int my_close(File fd, myf MyFlags)
if ((uint) fd < my_file_limit && my_file_info[fd].type != UNOPEN)
{
my_free(my_file_info[fd].name, MYF(0));
-#if defined(THREAD) && !defined(HAVE_PREAD)
- pthread_mutex_destroy(&my_file_info[fd].mutex);
-#endif
my_file_info[fd].type = UNOPEN;
}
my_file_opened--;
@@ -141,16 +118,12 @@ File my_register_filename(File fd, const char *FileName, enum file_type
type_of_file, uint error_message_number, myf MyFlags)
{
DBUG_ENTER("my_register_filename");
- if ((int) fd >= 0)
+ if ((int) fd >= MY_FILE_MIN)
{
if ((uint) fd >= my_file_limit)
{
-#if defined(THREAD) && !defined(HAVE_PREAD)
- my_errno= EMFILE;
-#else
thread_safe_increment(my_file_opened,&THR_LOCK_open);
DBUG_RETURN(fd); /* safeguard */
-#endif
}
else
{
@@ -160,9 +133,6 @@ File my_register_filename(File fd, const char *FileName, enum file_type
my_file_opened++;
my_file_total_opened++;
my_file_info[fd].type = type_of_file;
-#if defined(THREAD) && !defined(HAVE_PREAD)
- pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST);
-#endif
pthread_mutex_unlock(&THR_LOCK_open);
DBUG_PRINT("exit",("fd: %d",fd));
DBUG_RETURN(fd);
@@ -187,188 +157,7 @@ File my_register_filename(File fd, const char *FileName, enum file_type
DBUG_RETURN(-1);
}
-#ifdef __WIN__
-
-extern void __cdecl _dosmaperr(unsigned long);
-
-/*
- Open a file with sharing. Similar to _sopen() from libc, but allows managing
- share delete on win32
-
- SYNOPSIS
- my_sopen()
- path fully qualified file name
- oflag operation flags
- shflag share flag
- pmode permission flags
-
- RETURN VALUE
- File descriptor of opened file if success
- -1 and sets errno if fails.
-*/
-
-File my_sopen(const char *path, int oflag, int shflag, int pmode)
-{
- int fh; /* handle of opened file */
- int mask;
- HANDLE osfh; /* OS handle of opened file */
- DWORD fileaccess; /* OS file access (requested) */
- DWORD fileshare; /* OS file sharing mode */
- DWORD filecreate; /* OS method of opening/creating */
- DWORD fileattrib; /* OS file attribute flags */
- SECURITY_ATTRIBUTES SecurityAttributes;
-
- SecurityAttributes.nLength= sizeof(SecurityAttributes);
- SecurityAttributes.lpSecurityDescriptor= NULL;
- SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);
- /*
- * decode the access flags
- */
- switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
- case _O_RDONLY: /* read access */
- fileaccess= GENERIC_READ;
- break;
- case _O_WRONLY: /* write access */
- fileaccess= GENERIC_WRITE;
- break;
- case _O_RDWR: /* read and write access */
- fileaccess= GENERIC_READ | GENERIC_WRITE;
- break;
- default: /* error, bad oflag */
- errno= EINVAL;
- _doserrno= 0L; /* not an OS error */
- return -1;
- }
-
- /*
- * decode sharing flags
- */
- switch (shflag) {
- case _SH_DENYRW: /* exclusive access except delete */
- fileshare= FILE_SHARE_DELETE;
- break;
- case _SH_DENYWR: /* share read and delete access */
- fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE;
- break;
- case _SH_DENYRD: /* share write and delete access */
- fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- break;
- case _SH_DENYNO: /* share read, write and delete access */
- fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- break;
- case _SH_DENYRWD: /* exclusive access */
- fileshare= 0L;
- break;
- case _SH_DENYWRD: /* share read access */
- fileshare= FILE_SHARE_READ;
- break;
- case _SH_DENYRDD: /* share write access */
- fileshare= FILE_SHARE_WRITE;
- break;
- case _SH_DENYDEL: /* share read and write access */
- fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE;
- break;
- default: /* error, bad shflag */
- errno= EINVAL;
- _doserrno= 0L; /* not an OS error */
- return -1;
- }
-
- /*
- * decode open/create method flags
- */
- switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
- case 0:
- case _O_EXCL: /* ignore EXCL w/o CREAT */
- filecreate= OPEN_EXISTING;
- break;
-
- case _O_CREAT:
- filecreate= OPEN_ALWAYS;
- break;
-
- case _O_CREAT | _O_EXCL:
- case _O_CREAT | _O_TRUNC | _O_EXCL:
- filecreate= CREATE_NEW;
- break;
-
- case _O_TRUNC:
- case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */
- filecreate= TRUNCATE_EXISTING;
- break;
-
- case _O_CREAT | _O_TRUNC:
- filecreate= CREATE_ALWAYS;
- break;
-
- default:
- /* this can't happen ... all cases are covered */
- errno= EINVAL;
- _doserrno= 0L;
- return -1;
- }
-
- /*
- * decode file attribute flags if _O_CREAT was specified
- */
- fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */
- if (oflag & _O_CREAT)
- {
- _umask((mask= _umask(0)));
-
- if (!((pmode & ~mask) & _S_IWRITE))
- fileattrib= FILE_ATTRIBUTE_READONLY;
- }
-
- /*
- * Set temporary file (delete-on-close) attribute if requested.
- */
- if (oflag & _O_TEMPORARY)
- {
- fileattrib|= FILE_FLAG_DELETE_ON_CLOSE;
- fileaccess|= DELETE;
- }
-
- /*
- * Set temporary file (delay-flush-to-disk) attribute if requested.
- */
- if (oflag & _O_SHORT_LIVED)
- fileattrib|= FILE_ATTRIBUTE_TEMPORARY;
-
- /*
- * Set sequential or random access attribute if requested.
- */
- if (oflag & _O_SEQUENTIAL)
- fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN;
- else if (oflag & _O_RANDOM)
- fileattrib|= FILE_FLAG_RANDOM_ACCESS;
-
- /*
- * try to open/create the file
- */
- if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes,
- filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
- {
- /*
- * OS call to open/create file failed! map the error, release
- * the lock, and return -1. note that it's not necessary to
- * call _free_osfhnd (it hasn't been used yet).
- */
- _dosmaperr(GetLastError()); /* map error */
- return -1; /* return error to caller */
- }
-
- if ((fh= _open_osfhandle((intptr_t)osfh,
- oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1)
- {
- _dosmaperr(GetLastError()); /* map error */
- CloseHandle(osfh);
- }
-
- return fh; /* return handle */
-}
-#endif /* __WIN__ */
#ifdef EXTRA_DEBUG
diff --git a/mysys/my_pread.c b/mysys/my_pread.c
index 836f5a92963..6421a2da601 100644
--- a/mysys/my_pread.c
+++ b/mysys/my_pread.c
@@ -18,7 +18,7 @@
#include "my_base.h"
#include <m_string.h>
#include <errno.h>
-#ifdef HAVE_PREAD
+#ifndef _WIN32
#include <unistd.h>
#endif
@@ -48,9 +48,7 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
{
size_t readbytes;
int error= 0;
-#ifndef HAVE_PREAD
- int save_errno;
-#endif
+
#ifndef DBUG_OFF
char llbuf[22];
DBUG_ENTER("my_pread");
@@ -61,20 +59,15 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
for (;;)
{
errno= 0; /* Linux, Windows don't reset this on EOF/success */
-#ifndef HAVE_PREAD
- pthread_mutex_lock(&my_file_info[Filedes].mutex);
- readbytes= (uint) -1;
- error= (lseek(Filedes, offset, MY_SEEK_SET) == (my_off_t) -1 ||
- (readbytes= read(Filedes, Buffer, (uint) Count)) != Count);
- save_errno= errno;
- pthread_mutex_unlock(&my_file_info[Filedes].mutex);
- if (error)
- {
- errno= save_errno;
+#ifdef _WIN32
+ readbytes= my_win_pread(Filedes, Buffer, Count, offset);
#else
- if ((error= ((readbytes= pread(Filedes, Buffer, Count, offset)) != Count)))
- {
+ readbytes= pread(Filedes, Buffer, Count, offset);
#endif
+ error = (readbytes != Count);
+
+ if (error)
+ {
my_errno= errno ? errno : -1;
if (errno == 0 || (readbytes != (size_t) -1 &&
(MyFlags & (MY_NABP | MY_FNABP))))
@@ -91,19 +84,19 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
#endif
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
- if (readbytes == (size_t) -1)
- my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
- my_filename(Filedes),my_errno);
- else if (MyFlags & (MY_NABP | MY_FNABP))
- my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
- my_filename(Filedes),my_errno);
+ if (readbytes == (size_t) -1)
+ my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
+ my_filename(Filedes),my_errno);
+ else if (MyFlags & (MY_NABP | MY_FNABP))
+ my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
+ my_filename(Filedes),my_errno);
}
if (readbytes == (size_t) -1 || (MyFlags & (MY_FNABP | MY_NABP)))
- DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
+ DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
}
if (MyFlags & (MY_NABP | MY_FNABP))
- DBUG_RETURN(0); /* Read went ok; Return 0 */
- DBUG_RETURN(readbytes); /* purecov: inspected */
+ DBUG_RETURN(0); /* Read went ok; Return 0 */
+ DBUG_RETURN(readbytes); /* purecov: inspected */
}
} /* my_pread */
@@ -132,7 +125,7 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count,
my_off_t offset, myf MyFlags)
{
- size_t writenbytes, written;
+ size_t writtenbytes, written;
uint errors;
#ifndef DBUG_OFF
char llbuf[22];
@@ -146,28 +139,22 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count,
for (;;)
{
-#ifndef HAVE_PREAD
- int error;
- writenbytes= (size_t) -1;
- pthread_mutex_lock(&my_file_info[Filedes].mutex);
- error= (lseek(Filedes, offset, MY_SEEK_SET) != (my_off_t) -1 &&
- (writenbytes = write(Filedes, Buffer, (uint) Count)) == Count);
- pthread_mutex_unlock(&my_file_info[Filedes].mutex);
- if (error)
- break;
+#ifdef _WIN32
+ writtenbytes= my_win_pwrite(Filedes, Buffer, Count,offset);
#else
- if ((writenbytes= pwrite(Filedes, Buffer, Count,offset)) == Count)
+ writtenbytes= pwrite(Filedes, Buffer, Count, offset);
+#endif
+ if (writtenbytes == Count)
break;
my_errno= errno;
-#endif
- if (writenbytes != (size_t) -1)
+ if (writtenbytes != (size_t) -1)
{ /* Safegueard */
- written+=writenbytes;
- Buffer+=writenbytes;
- Count-=writenbytes;
- offset+=writenbytes;
+ written+=writtenbytes;
+ Buffer+=writtenbytes;
+ Count-=writtenbytes;
+ offset+=writtenbytes;
}
- DBUG_PRINT("error",("Write only %u bytes", (uint) writenbytes));
+ DBUG_PRINT("error",("Write only %u bytes", (uint) writtenbytes));
#ifndef NO_BACKGROUND
#ifdef THREAD
if (my_thread_var->abort)
@@ -180,15 +167,15 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count,
errors++;
continue;
}
- if ((writenbytes && writenbytes != (size_t) -1) || my_errno == EINTR)
+ if ((writtenbytes && writtenbytes != (size_t) -1) || my_errno == EINTR)
continue; /* Retry */
#endif
if (MyFlags & (MY_NABP | MY_FNABP))
{
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
- my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG),
- my_filename(Filedes),my_errno);
+ my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG),
+ my_filename(Filedes),my_errno);
}
DBUG_RETURN(MY_FILE_ERROR); /* Error on read */
}
@@ -198,5 +185,5 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count,
DBUG_EXECUTE_IF("check", my_seek(Filedes, -1, SEEK_SET, MYF(0)););
if (MyFlags & (MY_NABP | MY_FNABP))
DBUG_RETURN(0); /* Want only errors */
- DBUG_RETURN(writenbytes+written); /* purecov: inspected */
+ DBUG_RETURN(writtenbytes+written); /* purecov: inspected */
} /* my_pwrite */
diff --git a/mysys/my_quick.c b/mysys/my_quick.c
index 0ba20a5bdee..b93e7e17224 100644
--- a/mysys/my_quick.c
+++ b/mysys/my_quick.c
@@ -19,11 +19,19 @@
#include "my_nosys.h"
+#ifdef _WIN32
+extern size_t my_win_read(File Filedes,uchar *Buffer,size_t Count);
+#endif
+
size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags)
{
size_t readbytes;
-
- if ((readbytes = read(Filedes, Buffer, (uint) Count)) != Count)
+#ifdef _WIN32
+ readbytes= my_win_read(Filedes, Buffer, Count);
+#else
+ readbytes= read(Filedes, Buffer, Count);
+#endif
+ if(readbytes != Count)
{
#ifndef DBUG_OFF
if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR)
@@ -40,8 +48,13 @@ size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags)
}
-size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count)
+
+size_t my_quick_write(File Filedes, const uchar *Buffer, size_t Count)
{
+#ifdef _WIN32
+ return my_win_write(Filedes, Buffer, Count);
+#else
+
#ifndef DBUG_OFF
size_t writtenbytes;
#endif
@@ -50,7 +63,7 @@ size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count)
#ifndef DBUG_OFF
writtenbytes =
#endif
- (size_t) write(Filedes,Buffer, (uint) Count)) != Count)
+ (size_t) write(Filedes,Buffer,Count)) != Count)
{
#ifndef DBUG_OFF
if ((writtenbytes == 0 || writtenbytes == (size_t) -1) && errno == EINTR)
@@ -64,4 +77,5 @@ size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count)
return (size_t) -1;
}
return 0;
+#endif
}
diff --git a/mysys/my_read.c b/mysys/my_read.c
index 25ffe73d813..9c76193aa63 100644
--- a/mysys/my_read.c
+++ b/mysys/my_read.c
@@ -44,7 +44,12 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags)
for (;;)
{
errno= 0; /* Linux, Windows don't reset this on EOF/success */
- if ((readbytes= read(Filedes, Buffer, (uint) Count)) != Count)
+#ifdef _WIN32
+ readbytes= my_win_read(Filedes, Buffer, Count);
+#else
+ readbytes= my_read(Fildes, Buffer, Count);
+#endif
+ if (readbytes != Count)
{
my_errno= errno;
if (errno == 0 || (readbytes != (size_t) -1 &&
diff --git a/mysys/my_seek.c b/mysys/my_seek.c
index d186d56869a..24941517487 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -56,16 +56,11 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags)
Make sure we are using a valid file descriptor!
*/
DBUG_ASSERT(fd != -1);
-#if defined(THREAD) && !defined(HAVE_PREAD)
- if (MyFlags & MY_THREADSAFE)
- {
- pthread_mutex_lock(&my_file_info[fd].mutex);
- newpos= lseek(fd, pos, whence);
- pthread_mutex_unlock(&my_file_info[fd].mutex);
- }
- else
+#ifdef _WIN32
+ newpos= my_win_lseek(fd, pos, whence);
+#else
+ newpos= lseek(fd, pos, whence);
#endif
- newpos= lseek(fd, pos, whence);
if (newpos == (os_off_t) -1)
{
my_errno= errno;
@@ -91,7 +86,9 @@ my_off_t my_tell(File fd, myf MyFlags)
DBUG_ENTER("my_tell");
DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags));
DBUG_ASSERT(fd >= 0);
-#ifdef HAVE_TELL
+#ifdef _WIN32
+ pos= my_seek(fd, 0, MY_SEEK_CUR,0);
+#elif defined(HAVE_TELL)
pos=tell(fd);
#else
pos=lseek(fd, 0L, MY_SEEK_CUR);
diff --git a/mysys/my_static.c b/mysys/my_static.c
index 08653d03d21..629ee26efb9 100644
--- a/mysys/my_static.c
+++ b/mysys/my_static.c
@@ -35,7 +35,7 @@ int NEAR my_umask=0664, NEAR my_umask_dir=0777;
#ifndef THREAD
int NEAR my_errno=0;
#endif
-struct st_my_file_info my_file_info_default[MY_NFILE]= {{0,UNOPEN}};
+struct st_my_file_info my_file_info_default[MY_NFILE];
uint my_file_limit= MY_NFILE;
struct st_my_file_info *my_file_info= my_file_info_default;
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
index dae20b0163e..9c5fbce7ab7 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -71,7 +71,7 @@ int my_sync(File fd, myf my_flags)
if (res == -1 && errno == ENOLCK)
res= 0; /* Result Bug in Old FreeBSD */
#elif defined(__WIN__)
- res= _commit(fd);
+ res= my_win_fsync(fd);
#else
#error Cannot find a way to sync a file, durability in danger
res= 0; /* No sync (strange OS) */
diff --git a/mysys/my_winerr.c b/mysys/my_winerr.c
new file mode 100644
index 00000000000..534078b6737
--- /dev/null
+++ b/mysys/my_winerr.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2008 MySQL AB
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Convert Windows API error (GetLastError() to Posix equivalent (errno)
+ The exported function my_osmaperr() is modelled after and borrows
+ heavily from undocumented _dosmaperr()(found of the static Microsoft C runtime).
+*/
+
+#include <my_global.h>
+#include <my_sys.h>
+
+
+struct errentry
+{
+ unsigned long oscode; /* OS return value */
+ int sysv_errno; /* System V error code */
+};
+
+static struct errentry errtable[]= {
+ { ERROR_INVALID_FUNCTION, EINVAL }, /* 1 */
+ { ERROR_FILE_NOT_FOUND, ENOENT }, /* 2 */
+ { ERROR_PATH_NOT_FOUND, ENOENT }, /* 3 */
+ { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, /* 4 */
+ { ERROR_ACCESS_DENIED, EACCES }, /* 5 */
+ { ERROR_INVALID_HANDLE, EBADF }, /* 6 */
+ { ERROR_ARENA_TRASHED, ENOMEM }, /* 7 */
+ { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, /* 8 */
+ { ERROR_INVALID_BLOCK, ENOMEM }, /* 9 */
+ { ERROR_BAD_ENVIRONMENT, E2BIG }, /* 10 */
+ { ERROR_BAD_FORMAT, ENOEXEC }, /* 11 */
+ { ERROR_INVALID_ACCESS, EINVAL }, /* 12 */
+ { ERROR_INVALID_DATA, EINVAL }, /* 13 */
+ { ERROR_INVALID_DRIVE, ENOENT }, /* 15 */
+ { ERROR_CURRENT_DIRECTORY, EACCES }, /* 16 */
+ { ERROR_NOT_SAME_DEVICE, EXDEV }, /* 17 */
+ { ERROR_NO_MORE_FILES, ENOENT }, /* 18 */
+ { ERROR_LOCK_VIOLATION, EACCES }, /* 33 */
+ { ERROR_BAD_NETPATH, ENOENT }, /* 53 */
+ { ERROR_NETWORK_ACCESS_DENIED, EACCES }, /* 65 */
+ { ERROR_BAD_NET_NAME, ENOENT }, /* 67 */
+ { ERROR_FILE_EXISTS, EEXIST }, /* 80 */
+ { ERROR_CANNOT_MAKE, EACCES }, /* 82 */
+ { ERROR_FAIL_I24, EACCES }, /* 83 */
+ { ERROR_INVALID_PARAMETER, EINVAL }, /* 87 */
+ { ERROR_NO_PROC_SLOTS, EAGAIN }, /* 89 */
+ { ERROR_DRIVE_LOCKED, EACCES }, /* 108 */
+ { ERROR_BROKEN_PIPE, EPIPE }, /* 109 */
+ { ERROR_DISK_FULL, ENOSPC }, /* 112 */
+ { ERROR_INVALID_TARGET_HANDLE, EBADF }, /* 114 */
+ { ERROR_INVALID_HANDLE, EINVAL }, /* 124 */
+ { ERROR_WAIT_NO_CHILDREN, ECHILD }, /* 128 */
+ { ERROR_CHILD_NOT_COMPLETE, ECHILD }, /* 129 */
+ { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, /* 130 */
+ { ERROR_NEGATIVE_SEEK, EINVAL }, /* 131 */
+ { ERROR_SEEK_ON_DEVICE, EACCES }, /* 132 */
+ { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, /* 145 */
+ { ERROR_NOT_LOCKED, EACCES }, /* 158 */
+ { ERROR_BAD_PATHNAME, ENOENT }, /* 161 */
+ { ERROR_MAX_THRDS_REACHED, EAGAIN }, /* 164 */
+ { ERROR_LOCK_FAILED, EACCES }, /* 167 */
+ { ERROR_ALREADY_EXISTS, EEXIST }, /* 183 */
+ { ERROR_FILENAME_EXCED_RANGE, ENOENT }, /* 206 */
+ { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, /* 215 */
+ { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } /* 1816 */
+};
+
+/* size of the table */
+#define ERRTABLESIZE (sizeof(errtable)/sizeof(errtable[0]))
+
+/* The following two constants must be the minimum and maximum
+values in the (contiguous) range of Exec Failure errors. */
+#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
+#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
+
+/* These are the low and high value in the range of errors that are
+access violations */
+#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
+#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
+
+
+static int get_errno_from_oserr(unsigned long oserrno)
+{
+ int i;
+
+ /* check the table for the OS error code */
+ for (i= 0; i < ERRTABLESIZE; ++i)
+ {
+ if (oserrno == errtable[i].oscode)
+ {
+ return errtable[i].sysv_errno;
+ }
+ }
+
+ /* The error code wasn't in the table. We check for a range of */
+ /* EACCES errors or exec failure errors (ENOEXEC). Otherwise */
+ /* EINVAL is returned. */
+
+ if (oserrno >= MIN_EACCES_RANGE && oserrno <= MAX_EACCES_RANGE)
+ return EACCES;
+ else if (oserrno >= MIN_EXEC_ERROR && oserrno <= MAX_EXEC_ERROR)
+ return ENOEXEC;
+ else
+ return EINVAL;
+}
+
+/* Set errno corresponsing to GetLastError() value */
+void my_osmaperr ( unsigned long oserrno)
+{
+ errno= get_errno_from_oserr(oserrno);
+}
diff --git a/mysys/my_winfile.c b/mysys/my_winfile.c
new file mode 100644
index 00000000000..f63c35ba47b
--- /dev/null
+++ b/mysys/my_winfile.c
@@ -0,0 +1,681 @@
+/* Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ The purpose of this file is to provide implementation of file IO routines on
+ Windows that can be thought as drop-in replacement for corresponding C runtime
+ functionality.
+
+ Compared to Windows CRT, this one
+ - does not have the same file descriptor
+ limitation (default is 16384 and can be increased further, whereas CRT poses
+ a hard limit of 2048 file descriptors)
+ - the file operations are not serialized
+ - positional IO pread/pwrite is ported here.
+ - no text mode for files, all IO is "binary"
+
+ Naming convention:
+ All routines are prefixed with my_win_, e.g Posix open() is implemented with
+ my_win_open()
+
+ Implemented are
+ - POSIX routines(e.g open, read, lseek ...)
+ - Some ANSI C stream routines (fopen, fdopen, fileno, fclose)
+ - Windows CRT equvalients (my_get_osfhandle, open_osfhandle)
+
+ Worth to note:
+ - File descriptors used here are located in a range that is not compatible
+ with CRT on purpose. Attempt to use a file descriptor from Windows CRT library
+ range in my_win_* function will be punished with DBUG_ASSERT()
+
+ - File streams (FILE *) are actually from the C runtime. The routines provided
+ here are useful only in scernarios that use low-level IO with my_win_fileno()
+*/
+
+#ifdef _WIN32
+
+#include "mysys_priv.h"
+#include <share.h>
+#include <sys/stat.h>
+
+/* Associates a file descriptor with an existing operating-system file handle.*/
+File my_open_osfhandle(HANDLE handle, int oflag)
+{
+ int offset= -1;
+ uint i;
+ DBUG_ENTER("my_open_osfhandle");
+
+ pthread_mutex_lock(&THR_LOCK_open);
+ for(i= MY_FILE_MIN; i < my_file_limit;i++)
+ {
+ if(my_file_info[i].fhandle == 0)
+ {
+ struct st_my_file_info *finfo= &(my_file_info[i]);
+ finfo->type= FILE_BY_OPEN;
+ finfo->fhandle= handle;
+ finfo->oflag= oflag;
+ offset= i;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&THR_LOCK_open);
+ if(offset == -1)
+ errno= EMFILE; /* to many file handles open */
+ DBUG_RETURN(offset);
+}
+
+
+static void invalidate_fd(File fd)
+{
+ DBUG_ENTER("invalidate_fd");
+ DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit);
+ my_file_info[fd].fhandle= 0;
+ DBUG_VOID_RETURN;
+}
+
+
+/* Get Windows handle for a file descriptor */
+HANDLE my_get_osfhandle(File fd)
+{
+ DBUG_ENTER("my_get_osfhandle");
+ DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit);
+ DBUG_RETURN(my_file_info[fd].fhandle);
+}
+
+
+static int my_get_open_flags(File fd)
+{
+ DBUG_ENTER("my_get_open_flags");
+ DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit);
+ DBUG_RETURN(my_file_info[fd].oflag);
+}
+
+
+/*
+ Open a file with sharing. Similar to _sopen() from libc, but allows managing
+ share delete on win32
+
+ SYNOPSIS
+ my_win_sopen()
+ path file name
+ oflag operation flags
+ shflag share flag
+ pmode permission flags
+
+ RETURN VALUE
+ File descriptor of opened file if success
+ -1 and sets errno if fails.
+*/
+
+File my_win_sopen(const char *path, int oflag, int shflag, int pmode)
+{
+ int fh; /* handle of opened file */
+ int mask;
+ HANDLE osfh; /* OS handle of opened file */
+ DWORD fileaccess; /* OS file access (requested) */
+ DWORD fileshare; /* OS file sharing mode */
+ DWORD filecreate; /* OS method of opening/creating */
+ DWORD fileattrib; /* OS file attribute flags */
+ SECURITY_ATTRIBUTES SecurityAttributes;
+
+ DBUG_ENTER("my_win_sopen");
+
+ if (check_if_legal_filename(path))
+ {
+ errno= EACCES;
+ DBUG_RETURN(-1);
+ }
+ SecurityAttributes.nLength= sizeof(SecurityAttributes);
+ SecurityAttributes.lpSecurityDescriptor= NULL;
+ SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);
+
+ /* decode the access flags */
+ switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
+ case _O_RDONLY: /* read access */
+ fileaccess= GENERIC_READ;
+ break;
+ case _O_WRONLY: /* write access */
+ fileaccess= GENERIC_WRITE;
+ break;
+ case _O_RDWR: /* read and write access */
+ fileaccess= GENERIC_READ | GENERIC_WRITE;
+ break;
+ default: /* error, bad oflag */
+ errno= EINVAL;
+ DBUG_RETURN(-1);
+ }
+
+ /* decode sharing flags */
+ switch (shflag) {
+ case _SH_DENYRW: /* exclusive access except delete */
+ fileshare= FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYWR: /* share read and delete access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYRD: /* share write and delete access */
+ fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYNO: /* share read, write and delete access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYRWD: /* exclusive access */
+ fileshare= 0L;
+ break;
+ case _SH_DENYWRD: /* share read access */
+ fileshare= FILE_SHARE_READ;
+ break;
+ case _SH_DENYRDD: /* share write access */
+ fileshare= FILE_SHARE_WRITE;
+ break;
+ case _SH_DENYDEL: /* share read and write access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE;
+ break;
+ default: /* error, bad shflag */
+ errno= EINVAL;
+ DBUG_RETURN(-1);
+ }
+
+ /* decode open/create method flags */
+ switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
+ case 0:
+ case _O_EXCL: /* ignore EXCL w/o CREAT */
+ filecreate= OPEN_EXISTING;
+ break;
+
+ case _O_CREAT:
+ filecreate= OPEN_ALWAYS;
+ break;
+
+ case _O_CREAT | _O_EXCL:
+ case _O_CREAT | _O_TRUNC | _O_EXCL:
+ filecreate= CREATE_NEW;
+ break;
+
+ case _O_TRUNC:
+ case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */
+ filecreate= TRUNCATE_EXISTING;
+ break;
+
+ case _O_CREAT | _O_TRUNC:
+ filecreate= CREATE_ALWAYS;
+ break;
+
+ default:
+ /* this can't happen ... all cases are covered */
+ errno= EINVAL;
+ DBUG_RETURN(-1);
+ }
+
+ /* decode file attribute flags if _O_CREAT was specified */
+ fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */
+ if (oflag & _O_CREAT)
+ {
+ _umask((mask= _umask(0)));
+
+ if (!((pmode & ~mask) & _S_IWRITE))
+ fileattrib= FILE_ATTRIBUTE_READONLY;
+ }
+
+ /* Set temporary file (delete-on-close) attribute if requested. */
+ if (oflag & _O_TEMPORARY)
+ {
+ fileattrib|= FILE_FLAG_DELETE_ON_CLOSE;
+ fileaccess|= DELETE;
+ }
+
+ /* Set temporary file (delay-flush-to-disk) attribute if requested.*/
+ if (oflag & _O_SHORT_LIVED)
+ fileattrib|= FILE_ATTRIBUTE_TEMPORARY;
+
+ /* Set sequential or random access attribute if requested. */
+ if (oflag & _O_SEQUENTIAL)
+ fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN;
+ else if (oflag & _O_RANDOM)
+ fileattrib|= FILE_FLAG_RANDOM_ACCESS;
+
+ /* try to open/create the file */
+ if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes,
+ filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
+ {
+ /*
+ OS call to open/create file failed! map the error, release
+ the lock, and return -1. note that it's not necessary to
+ call _free_osfhnd (it hasn't been used yet).
+ */
+ my_osmaperr(GetLastError()); /* map error */
+ DBUG_RETURN(-1); /* return error to caller */
+ }
+
+ if ((fh= my_open_osfhandle(osfh,
+ oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1)
+ {
+ CloseHandle(osfh);
+ }
+
+ DBUG_RETURN(fh); /* return handle */
+}
+
+
+File my_win_open(const char *path, int flags)
+{
+ DBUG_ENTER("my_win_open");
+ DBUG_RETURN(my_win_sopen((char *) path, flags | _O_BINARY, _SH_DENYNO,
+ _S_IREAD | S_IWRITE));
+}
+
+
+int my_win_close(File fd)
+{
+ DBUG_ENTER("my_win_close");
+ if(CloseHandle(my_get_osfhandle(fd)))
+ {
+ invalidate_fd(fd);
+ DBUG_RETURN(0);
+ }
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+}
+
+
+size_t my_win_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset)
+{
+ DWORD nBytesRead;
+ HANDLE hFile;
+ OVERLAPPED ov= {0};
+ LARGE_INTEGER li;
+
+ DBUG_ENTER("my_win_pread");
+
+ if(!Count)
+ DBUG_RETURN(0);
+#ifdef _WIN64
+ if(Count > UINT_MAX)
+ Count= UINT_MAX;
+#endif
+
+ hFile= (HANDLE)my_get_osfhandle(Filedes);
+ li.QuadPart= offset;
+ ov.Offset= li.LowPart;
+ ov.OffsetHigh= li.HighPart;
+
+ if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, &ov))
+ {
+ DWORD lastError= GetLastError();
+ /*
+ ERROR_BROKEN_PIPE is returned when no more data coming
+ through e.g. a command pipe in windows : see MSDN on ReadFile.
+ */
+ if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE)
+ DBUG_RETURN(0); /*return 0 at EOF*/
+ my_osmaperr(lastError);
+ DBUG_RETURN((size_t)-1);
+ }
+ DBUG_RETURN(nBytesRead);
+}
+
+
+size_t my_win_read(File Filedes, uchar *Buffer, size_t Count)
+{
+ DWORD nBytesRead;
+ HANDLE hFile;
+
+ DBUG_ENTER("my_win_read");
+ if(!Count)
+ DBUG_RETURN(0);
+#ifdef _WIN64
+ if(Count > UINT_MAX)
+ Count= UINT_MAX;
+#endif
+
+ hFile= (HANDLE)my_get_osfhandle(Filedes);
+
+ if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, NULL))
+ {
+ DWORD lastError= GetLastError();
+ /*
+ ERROR_BROKEN_PIPE is returned when no more data coming
+ through e.g. a command pipe in windows : see MSDN on ReadFile.
+ */
+ if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE)
+ DBUG_RETURN(0); /*return 0 at EOF*/
+ my_osmaperr(lastError);
+ DBUG_RETURN((size_t)-1);
+ }
+ DBUG_RETURN(nBytesRead);
+}
+
+
+size_t my_win_pwrite(File Filedes, const uchar *Buffer, size_t Count,
+ my_off_t offset)
+{
+ DWORD nBytesWritten;
+ HANDLE hFile;
+ OVERLAPPED ov= {0};
+ LARGE_INTEGER li;
+
+ DBUG_ENTER("my_win_pwrite");
+ DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count: %llu, offset: %llu",
+ Filedes, Buffer, (ulonglong)Count, (ulonglong)offset));
+
+ if(!Count)
+ DBUG_RETURN(0);
+
+#ifdef _WIN64
+ if(Count > UINT_MAX)
+ Count= UINT_MAX;
+#endif
+
+ hFile= (HANDLE)my_get_osfhandle(Filedes);
+ li.QuadPart= offset;
+ ov.Offset= li.LowPart;
+ ov.OffsetHigh= li.HighPart;
+
+ if(!WriteFile(hFile, Buffer, (DWORD)Count, &nBytesWritten, &ov))
+ {
+ my_osmaperr(GetLastError());
+ DBUG_RETURN((size_t)-1);
+ }
+ else
+ DBUG_RETURN(nBytesWritten);
+}
+
+
+my_off_t my_win_lseek(File fd, my_off_t pos, int whence)
+{
+ LARGE_INTEGER offset;
+ LARGE_INTEGER newpos;
+
+ DBUG_ENTER("my_win_lseek");
+
+ /* Check compatibility of Windows and Posix seek constants */
+ compile_time_assert(FILE_BEGIN == SEEK_SET && FILE_CURRENT == SEEK_CUR
+ && FILE_END == SEEK_END);
+
+ offset.QuadPart= pos;
+ if(!SetFilePointerEx(my_get_osfhandle(fd), offset, &newpos, whence))
+ {
+ my_osmaperr(GetLastError());
+ newpos.QuadPart= -1;
+ }
+ DBUG_RETURN(newpos.QuadPart);
+}
+
+
+#ifndef FILE_WRITE_TO_END_OF_FILE
+#define FILE_WRITE_TO_END_OF_FILE 0xffffffff
+#endif
+size_t my_win_write(File fd, const uchar *Buffer, size_t Count)
+{
+ DWORD nWritten;
+ OVERLAPPED ov;
+ OVERLAPPED *pov= NULL;
+ HANDLE hFile;
+
+ DBUG_ENTER("my_win_write");
+ DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count %llu", fd, Buffer,
+ (ulonglong)Count));
+
+ if(!Count)
+ DBUG_RETURN(0);
+
+#ifdef _WIN64
+ if(Count > UINT_MAX)
+ Count= UINT_MAX;
+#endif
+
+ if(my_get_open_flags(fd) & _O_APPEND)
+ {
+ /*
+ Atomic append to the end of file is is done by special initialization of
+ the OVERLAPPED structure. See MSDN WriteFile documentation for more info.
+ */
+ memset(&ov, 0, sizeof(ov));
+ ov.Offset= FILE_WRITE_TO_END_OF_FILE;
+ ov.OffsetHigh= -1;
+ pov= &ov;
+ }
+
+ hFile= my_get_osfhandle(fd);
+ if(!WriteFile(hFile, Buffer, (DWORD)Count, &nWritten, pov))
+ {
+ my_osmaperr(GetLastError());
+ DBUG_RETURN((size_t)-1);
+ }
+ DBUG_RETURN(nWritten);
+}
+
+
+int my_win_chsize(File fd, my_off_t newlength)
+{
+ HANDLE hFile;
+ LARGE_INTEGER length;
+ DBUG_ENTER("my_win_chsize");
+
+ hFile= (HANDLE) my_get_osfhandle(fd);
+ length.QuadPart= newlength;
+ if (!SetFilePointerEx(hFile, length , NULL , FILE_BEGIN))
+ goto err;
+ if (!SetEndOfFile(hFile))
+ goto err;
+ DBUG_RETURN(0);
+err:
+ my_osmaperr(GetLastError());
+ my_errno= errno;
+ DBUG_RETURN(-1);
+}
+
+
+/* Get the file descriptor for stdin,stdout or stderr */
+static File my_get_stdfile_descriptor(FILE *stream)
+{
+ HANDLE hFile;
+ DWORD nStdHandle;
+ DBUG_ENTER("my_get_stdfile_descriptor");
+
+ if(stream == stdin)
+ nStdHandle= STD_INPUT_HANDLE;
+ else if(stream == stdout)
+ nStdHandle= STD_OUTPUT_HANDLE;
+ else if(stream == stderr)
+ nStdHandle= STD_ERROR_HANDLE;
+ else
+ DBUG_RETURN(-1);
+
+ hFile= GetStdHandle(nStdHandle);
+ if(hFile != INVALID_HANDLE_VALUE)
+ DBUG_RETURN(my_open_osfhandle(hFile, 0));
+ DBUG_RETURN(-1);
+}
+
+
+File my_win_fileno(FILE *file)
+{
+ HANDLE hFile= (HANDLE)_get_osfhandle(fileno(file));
+ int retval= -1;
+ uint i;
+
+ DBUG_ENTER("my_win_fileno");
+
+ for(i= MY_FILE_MIN; i < my_file_limit; i++)
+ {
+ if(my_file_info[i].fhandle == hFile)
+ {
+ retval= i;
+ break;
+ }
+ }
+ if(retval == -1)
+ /* try std stream */
+ DBUG_RETURN(my_get_stdfile_descriptor(file));
+ DBUG_RETURN(retval);
+}
+
+
+FILE *my_win_fopen(const char *filename, const char *type)
+{
+ FILE *file;
+ int flags= 0;
+ DBUG_ENTER("my_win_open");
+
+ /*
+ If we are not creating, then we need to use my_access to make sure
+ the file exists since Windows doesn't handle files like "com1.sym"
+ very well
+ */
+ if (check_if_legal_filename(filename))
+ {
+ errno= EACCES;
+ DBUG_RETURN(NULL);
+ }
+
+ file= fopen(filename, type);
+ if(!file)
+ DBUG_RETURN(NULL);
+
+ if(strchr(type,'a') != NULL)
+ flags= O_APPEND;
+
+ /*
+ Register file handle in my_table_info.
+ Necessary for my_fileno()
+ */
+ if(my_open_osfhandle((HANDLE)_get_osfhandle(fileno(file)), flags) < 0)
+ {
+ fclose(file);
+ DBUG_RETURN(NULL);
+ }
+ DBUG_RETURN(file);
+}
+
+
+FILE * my_win_fdopen(File fd, const char *type)
+{
+ FILE *file;
+ int crt_fd;
+ int flags= 0;
+
+ DBUG_ENTER("my_win_fdopen");
+
+ if(strchr(type,'a') != NULL)
+ flags= O_APPEND;
+ /* Convert OS file handle to CRT file descriptor and then call fdopen*/
+ crt_fd= _open_osfhandle((intptr_t)my_get_osfhandle(fd), flags);
+ if(crt_fd < 0)
+ file= NULL;
+ else
+ file= fdopen(crt_fd, type);
+ DBUG_RETURN(file);
+}
+
+
+int my_win_fclose(FILE *file)
+{
+ File fd;
+
+ DBUG_ENTER("my_win_close");
+ fd= my_fileno(file);
+ if(fd < 0)
+ DBUG_RETURN(-1);
+ if(fclose(file) < 0)
+ DBUG_RETURN(-1);
+ invalidate_fd(fd);
+ DBUG_RETURN(0);
+}
+
+
+
+/*
+ Quick and dirty my_fstat() implementation for Windows.
+ Use CRT fstat on temporarily allocated file descriptor.
+ Patch file size, because size that fstat returns is not
+ reliable (may be outdated)
+*/
+int my_win_fstat(File fd, struct _stati64 *buf)
+{
+ int crt_fd;
+ int retval;
+ HANDLE hFile, hDup;
+
+ DBUG_ENTER("my_win_fstat");
+
+ hFile= my_get_osfhandle(fd);
+ if(!DuplicateHandle( GetCurrentProcess(), hFile, GetCurrentProcess(),
+ &hDup ,0,FALSE,DUPLICATE_SAME_ACCESS))
+ {
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+ }
+ if ((crt_fd= _open_osfhandle((intptr_t)hDup,0)) < 0)
+ DBUG_RETURN(-1);
+
+ retval= _fstati64(crt_fd, buf);
+ if(retval == 0)
+ {
+ /* File size returned by stat is not accurate (may be outdated), fix it*/
+ GetFileSizeEx(hDup, (PLARGE_INTEGER) (&(buf->st_size)));
+ }
+ _close(crt_fd);
+ DBUG_RETURN(retval);
+}
+
+
+
+int my_win_stat( const char *path, struct _stati64 *buf)
+{
+ DBUG_ENTER("my_win_stat");
+ if(_stati64( path, buf) == 0)
+ {
+ /* File size returned by stat is not accurate (may be outdated), fix it*/
+ WIN32_FILE_ATTRIBUTE_DATA data;
+ if (GetFileAttributesEx(path, GetFileExInfoStandard, &data))
+ {
+ LARGE_INTEGER li;
+ li.LowPart= data.nFileSizeLow;
+ li.HighPart= data.nFileSizeHigh;
+ buf->st_size= li.QuadPart;
+ }
+ DBUG_RETURN(0);
+ }
+ DBUG_RETURN(-1);
+}
+
+
+
+int my_win_fsync(File fd)
+{
+ DBUG_ENTER("my_win_fsync");
+ if(FlushFileBuffers(my_get_osfhandle(fd)))
+ DBUG_RETURN(0);
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+}
+
+
+
+int my_win_dup(File fd)
+{
+ HANDLE hDup;
+ DBUG_ENTER("my_win_dup");
+ if (DuplicateHandle(GetCurrentProcess(), my_get_osfhandle(fd),
+ GetCurrentProcess(), &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ DBUG_RETURN(my_open_osfhandle(hDup, my_get_open_flags(fd)));
+ }
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+}
+
+#endif /*_WIN32*/
diff --git a/mysys/my_write.c b/mysys/my_write.c
index 52127545888..5b916d6cb65 100644
--- a/mysys/my_write.c
+++ b/mysys/my_write.c
@@ -22,7 +22,7 @@
size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
{
- size_t writenbytes, written;
+ size_t writtenbytes, written;
uint errors;
DBUG_ENTER("my_write");
DBUG_PRINT("my",("fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d",
@@ -35,17 +35,27 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
for (;;)
{
- if ((writenbytes= write(Filedes, Buffer, Count)) == Count)
+#ifdef _WIN32
+ if(Filedes < 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ writtenbytes= my_win_write(Filedes, Buffer, Count);
+#else
+ writtenbytes= write(Filedes, Buffer, Count);
+#endif
+ if (writtenbytes == Count)
break;
- if (writenbytes != (size_t) -1)
+ if (writtenbytes != (size_t) -1)
{ /* Safeguard */
- written+=writenbytes;
- Buffer+=writenbytes;
- Count-=writenbytes;
+ written+= writtenbytes;
+ Buffer+= writtenbytes;
+ Count-= writtenbytes;
}
- my_errno=errno;
+ my_errno= errno;
DBUG_PRINT("error",("Write only %ld bytes, error: %d",
- (long) writenbytes, my_errno));
+ (long) writtenbytes, my_errno));
#ifndef NO_BACKGROUND
#ifdef THREAD
if (my_thread_var->abort)
@@ -59,19 +69,19 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
continue;
}
- if ((writenbytes == 0 || writenbytes == (size_t) -1))
+ if ((writtenbytes == 0 || writtenbytes == (size_t) -1))
{
if (my_errno == EINTR)
{
DBUG_PRINT("debug", ("my_write() was interrupted and returned %ld",
- (long) writenbytes));
+ (long) writtenbytes));
continue; /* Interrupted */
}
- if (!writenbytes && !errors++) /* Retry once */
+ if (!writtenbytes && !errors++) /* Retry once */
{
/* We may come here if the file quota is exeeded */
- errno=EFBIG; /* Assume this is the error */
+ errno= EFBIG; /* Assume this is the error */
continue;
}
}
@@ -92,5 +102,5 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
}
if (MyFlags & (MY_NABP | MY_FNABP))
DBUG_RETURN(0); /* Want only errors */
- DBUG_RETURN(writenbytes+written);
+ DBUG_RETURN(writtenbytes+written);
} /* my_write */
diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h
index 113b64005f2..6d39999aa86 100644
--- a/mysys/mysys_priv.h
+++ b/mysys/mysys_priv.h
@@ -45,3 +45,27 @@ extern pthread_mutex_t THR_LOCK_charset, THR_LOCK_time;
void my_error_unregister_all(void);
void my_thread_destroy_mutex(void);
my_bool my_wait_for_other_threads_to_die(uint number_of_threads);
+
+#ifdef _WIN32
+/* my_winfile.c exports, should not be used outside mysys */
+extern File my_win_open(const char *path, int oflag);
+extern int my_win_close(File fd);
+extern size_t my_win_read(File fd, uchar *buffer, size_t count);
+extern size_t my_win_write(File fd, const uchar *buffer, size_t count);
+extern size_t my_win_pread(File fd, uchar *buffer, size_t count,
+ my_off_t offset);
+extern size_t my_win_pwrite(File fd, const uchar *buffer, size_t count,
+ my_off_t offset);
+extern my_off_t my_win_lseek(File fd, my_off_t pos, int whence);
+extern int my_win_chsize(File fd, my_off_t newlength);
+extern FILE* my_win_fopen(const char *filename, const char *type);
+extern File my_win_fclose(FILE *file);
+extern File my_win_fileno(FILE *file);
+extern FILE* my_win_fdopen(File Filedes, const char *type);
+extern int my_win_stat(const char *path, struct _stat64 *buf);
+extern int my_win_fstat(File fd, struct _stat64 *buf);
+extern int my_win_fsync(File fd);
+extern File my_win_dup(File fd);
+extern File my_win_sopen(const char *path, int oflag, int shflag, int perm);
+extern File my_open_osfhandle(HANDLE handle, int oflag);
+#endif