mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
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
This commit is contained in:
parent
824ce5f3ea
commit
4171483b53
40 changed files with 1268 additions and 424 deletions
|
@ -2057,7 +2057,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
|
|||
return ERROR_STOP;
|
||||
}
|
||||
#endif
|
||||
if (init_io_cache(file, fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
|
||||
if (init_io_cache(file, my_fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
|
||||
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
|
||||
{
|
||||
error("Failed to init IO cache.");
|
||||
|
|
|
@ -1223,7 +1223,7 @@ get_options(int *argc,char ***argv)
|
|||
|
||||
if (opt_csv_str[0] == '-')
|
||||
{
|
||||
csv_file= fileno(stdout);
|
||||
csv_file= my_fileno(stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -43,7 +43,7 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
|
|||
if (!(line_buff=(LINE_BUFFER*)
|
||||
my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
|
||||
return 0;
|
||||
if (init_line_buffer(line_buff,fileno(file),IO_SIZE,max_size))
|
||||
if (init_line_buffer(line_buff,my_fileno(file),IO_SIZE,max_size))
|
||||
{
|
||||
my_free(line_buff,MYF(0));
|
||||
return 0;
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
#endif
|
||||
|
||||
/* File and lock constants */
|
||||
#define O_SHARE 0x1000 /* Open file in sharing mode */
|
||||
#ifdef __BORLANDC__
|
||||
#define F_RDLCK LK_NBLCK /* read lock */
|
||||
#define F_WRLCK LK_NBRLCK /* write lock */
|
||||
|
@ -374,7 +373,7 @@ inline ulonglong double2ulonglong(double d)
|
|||
#define FN_DEVCHAR ':'
|
||||
#define FN_NETWORK_DRIVES /* Uses \\ to indicate network drives */
|
||||
#define FN_NO_CASE_SENCE /* Files are not case-sensitive */
|
||||
#define OS_FILE_LIMIT 2048
|
||||
#define OS_FILE_LIMIT UINT_MAX
|
||||
|
||||
#define DO_NOT_REMOVE_THREAD_WRAPPERS
|
||||
#define thread_safe_increment(V,L) InterlockedIncrement((long*) &(V))
|
||||
|
|
|
@ -69,7 +69,11 @@ typedef struct my_stat
|
|||
|
||||
#else
|
||||
|
||||
#if(_MSC_VER)
|
||||
#define MY_STAT struct _stati64 /* 64 bit file size */
|
||||
#else
|
||||
#define MY_STAT struct stat /* Orginal struct have what we need */
|
||||
#endif
|
||||
|
||||
#endif /* USE_MY_STAT_STRUCT */
|
||||
|
||||
|
|
|
@ -784,7 +784,41 @@ typedef SOCKET_SIZE_TYPE size_socket;
|
|||
#define FN_DIRSEP "/" /* Valid directory separators */
|
||||
#define FN_ROOTDIR "/"
|
||||
#endif
|
||||
#define MY_NFILE 64 /* This is only used to save filenames */
|
||||
|
||||
/*
|
||||
MY_FILE_MIN is Windows speciality and is used to quickly detect
|
||||
the mismatch of CRT and mysys file IO usage on Windows at runtime.
|
||||
CRT file descriptors can be in the range 0-2047, whereas descriptors returned
|
||||
by my_open() will start with 2048. If a file descriptor with value less then
|
||||
MY_FILE_MIN is passed to mysys IO function, chances are it stemms from
|
||||
open()/fileno() and not my_open()/my_fileno.
|
||||
|
||||
For Posix, mysys functions are light wrappers around libc, and MY_FILE_MIN
|
||||
is logically 0.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MY_FILE_MIN 2048
|
||||
#else
|
||||
#define MY_FILE_MIN 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
MY_NFILE is the default size of my_file_info array.
|
||||
|
||||
It is larger on Windows, because it all file handles are stored in my_file_info
|
||||
Default size is 16384 and this should be enough for most cases.If it is not
|
||||
enough, --max-open-files with larger value can be used.
|
||||
|
||||
For Posix , my_file_info array is only used to store filenames for
|
||||
error reporting and its size is not a limitation for number of open files.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define MY_NFILE (16384 + MY_FILE_MIN)
|
||||
#else
|
||||
#define MY_NFILE 64
|
||||
#endif
|
||||
|
||||
#ifndef OS_FILE_LIMIT
|
||||
#define OS_FILE_LIMIT UINT_MAX
|
||||
#endif
|
||||
|
@ -821,9 +855,8 @@ typedef SOCKET_SIZE_TYPE size_socket;
|
|||
/* Some things that this system doesn't have */
|
||||
|
||||
#define NO_HASH /* Not needed anymore */
|
||||
#ifdef __WIN__
|
||||
#define NO_DIR_LIBRARY /* Not standar dir-library */
|
||||
#define USE_MY_STAT_STRUCT /* For my_lib */
|
||||
#ifdef _WIN32
|
||||
#define NO_DIR_LIBRARY /* Not standard dir-library */
|
||||
#endif
|
||||
|
||||
/* Some defines of functions for portability */
|
||||
|
|
|
@ -342,11 +342,12 @@ enum file_type
|
|||
|
||||
struct st_my_file_info
|
||||
{
|
||||
char * name;
|
||||
enum file_type type;
|
||||
#if defined(THREAD) && !defined(HAVE_PREAD)
|
||||
pthread_mutex_t mutex;
|
||||
char *name;
|
||||
#ifdef _WIN32
|
||||
HANDLE fhandle; /* win32 file handle */
|
||||
int oflag; /* open flags, e.g O_APPEND */
|
||||
#endif
|
||||
enum file_type type;
|
||||
};
|
||||
|
||||
extern struct st_my_file_info *my_file_info;
|
||||
|
@ -650,12 +651,12 @@ extern void *my_memmem(const void *haystack, size_t haystacklen,
|
|||
const void *needle, size_t needlelen);
|
||||
|
||||
|
||||
#ifdef __WIN__
|
||||
extern int my_access(const char *path, int amode);
|
||||
extern File my_sopen(const char *path, int oflag, int shflag, int pmode);
|
||||
#ifdef _WIN32
|
||||
extern int my_access(const char *path, int amode);
|
||||
#else
|
||||
#define my_access access
|
||||
#endif
|
||||
|
||||
extern int check_if_legal_filename(const char *path);
|
||||
extern int check_if_legal_tablename(const char *path);
|
||||
|
||||
|
@ -666,6 +667,13 @@ extern int nt_share_delete(const char *name,myf MyFlags);
|
|||
#define my_delete_allow_opened(fname,flags) my_delete((fname),(flags))
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Windows-only functions (CRT equivalents)*/
|
||||
extern File my_sopen(const char *path, int oflag, int shflag, int pmode);
|
||||
extern HANDLE my_get_osfhandle(File fd);
|
||||
extern void my_osmaperr(unsigned long last_error);
|
||||
#endif
|
||||
|
||||
#ifndef TERMINATE
|
||||
extern void TERMINATE(FILE *file, uint flag);
|
||||
#endif
|
||||
|
@ -675,6 +683,7 @@ extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags);
|
|||
extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags);
|
||||
extern FILE *my_freopen(const char *path, const char *mode, FILE *stream);
|
||||
extern int my_fclose(FILE *fd,myf MyFlags);
|
||||
extern File my_fileno(FILE *fd);
|
||||
extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags);
|
||||
extern int my_chmod(const char *name, mode_t mode, myf my_flags);
|
||||
extern int my_sync(File fd, myf my_flags);
|
||||
|
|
|
@ -87,6 +87,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c
|
|||
../mysys/my_static.c ../strings/my_strtoll10.c ../mysys/my_symlink.c
|
||||
../mysys/my_symlink2.c ../mysys/my_thr_init.c ../sql-common/my_time.c
|
||||
../strings/my_vsnprintf.c ../mysys/my_wincond.c ../mysys/my_winthread.c
|
||||
../mysys/my_wincond.c ../mysys/my_winthread.c ../mysys/my_winfile.c ../mysys/my_winerr.c
|
||||
../mysys/my_write.c ../sql/net_serv.cc ../sql-common/pack.c ../sql/password.c
|
||||
../mysys/safemalloc.c ../mysys/sha1.c ../strings/str2int.c
|
||||
../strings/str_alloc.c ../strings/strcend.c ../strings/strcont.c ../strings/strend.c
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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.*/
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
137
mysys/my_lock.c
137
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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
227
mysys/my_open.c
227
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
|
||||
|
|
|
@ -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);
|
||||
#ifdef _WIN32
|
||||
readbytes= my_win_pread(Filedes, Buffer, Count, offset);
|
||||
#else
|
||||
readbytes= pread(Filedes, Buffer, Count, offset);
|
||||
#endif
|
||||
error = (readbytes != Count);
|
||||
|
||||
if (error)
|
||||
{
|
||||
errno= save_errno;
|
||||
#else
|
||||
if ((error= ((readbytes= pread(Filedes, Buffer, Count, offset)) != Count)))
|
||||
{
|
||||
#endif
|
||||
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 */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) */
|
||||
|
|
123
mysys/my_winerr.c
Normal file
123
mysys/my_winerr.c
Normal file
|
@ -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);
|
||||
}
|
681
mysys/my_winfile.c
Normal file
681
mysys/my_winfile.c
Normal file
|
@ -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*/
|
|
@ -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)
|
||||
break;
|
||||
if (writenbytes != (size_t) -1)
|
||||
{ /* Safeguard */
|
||||
written+=writenbytes;
|
||||
Buffer+=writenbytes;
|
||||
Count-=writenbytes;
|
||||
#ifdef _WIN32
|
||||
if(Filedes < 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
my_errno=errno;
|
||||
writtenbytes= my_win_write(Filedes, Buffer, Count);
|
||||
#else
|
||||
writtenbytes= write(Filedes, Buffer, Count);
|
||||
#endif
|
||||
if (writtenbytes == Count)
|
||||
break;
|
||||
if (writtenbytes != (size_t) -1)
|
||||
{ /* Safeguard */
|
||||
written+= writtenbytes;
|
||||
Buffer+= writtenbytes;
|
||||
Count-= writtenbytes;
|
||||
}
|
||||
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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -67,7 +67,7 @@ int readfrm(const char *name, uchar **frmdata, size_t *len)
|
|||
error= 2;
|
||||
if (my_fstat(file, &state, MYF(0)))
|
||||
goto err;
|
||||
read_len= state.st_size;
|
||||
read_len= (size_t)state.st_size;
|
||||
|
||||
// Read whole frm file
|
||||
error= 3;
|
||||
|
|
|
@ -3025,16 +3025,16 @@ String *Item_load_file::val_str(String *str)
|
|||
func_name(), current_thd->variables.max_allowed_packet);
|
||||
goto err;
|
||||
}
|
||||
if (tmp_value.alloc(stat_info.st_size))
|
||||
if (tmp_value.alloc((size_t)stat_info.st_size))
|
||||
goto err;
|
||||
if ((file = my_open(file_name->ptr(), O_RDONLY, MYF(0))) < 0)
|
||||
goto err;
|
||||
if (my_read(file, (uchar*) tmp_value.ptr(), stat_info.st_size, MYF(MY_NABP)))
|
||||
if (my_read(file, (uchar*) tmp_value.ptr(), (size_t)stat_info.st_size, MYF(MY_NABP)))
|
||||
{
|
||||
my_close(file, MYF(0));
|
||||
goto err;
|
||||
}
|
||||
tmp_value.length(stat_info.st_size);
|
||||
tmp_value.length((uint32)stat_info.st_size);
|
||||
my_close(file, MYF(0));
|
||||
null_value = 0;
|
||||
DBUG_RETURN(&tmp_value);
|
||||
|
|
|
@ -684,11 +684,11 @@ int ha_archive::create(const char *name, TABLE *table_arg,
|
|||
{
|
||||
if (!my_fstat(frm_file, &file_stat, MYF(MY_WME)))
|
||||
{
|
||||
frm_ptr= (uchar *)my_malloc(sizeof(uchar) * file_stat.st_size, MYF(0));
|
||||
frm_ptr= (uchar *)my_malloc(sizeof(uchar) * (size_t)file_stat.st_size, MYF(0));
|
||||
if (frm_ptr)
|
||||
{
|
||||
my_read(frm_file, frm_ptr, file_stat.st_size, MYF(0));
|
||||
azwrite_frm(&create_stream, (char *)frm_ptr, file_stat.st_size);
|
||||
my_read(frm_file, frm_ptr, (size_t)file_stat.st_size, MYF(0));
|
||||
azwrite_frm(&create_stream, (char *)frm_ptr, (size_t)file_stat.st_size);
|
||||
my_free((uchar*)frm_ptr, MYF(0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1061,7 +1061,29 @@ innobase_mysql_tmpfile(void)
|
|||
will be passed to fdopen(), it will be closed by invoking
|
||||
fclose(), which in turn will invoke close() instead of
|
||||
my_close(). */
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Note that on Windows, the integer returned by mysql_tmpfile
|
||||
has no relation to C runtime file descriptor. Here, we need
|
||||
to call my_get_osfhandle to get the HANDLE and then convert it
|
||||
to C runtime filedescriptor. */
|
||||
{
|
||||
HANDLE hFile = my_get_osfhandle(fd);
|
||||
HANDLE hDup;
|
||||
BOOL bOK =
|
||||
DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(),
|
||||
&hDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
if(bOK) {
|
||||
fd2 = _open_osfhandle((intptr_t)hDup,0);
|
||||
}
|
||||
else {
|
||||
my_osmaperr(GetLastError());
|
||||
fd2 = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
fd2 = dup(fd);
|
||||
#endif
|
||||
if (fd2 < 0) {
|
||||
DBUG_PRINT("error",("Got error %d on dup",fd2));
|
||||
my_errno=errno;
|
||||
|
|
|
@ -48,7 +48,9 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include <m_ctype.h>
|
||||
#include <mysys_err.h>
|
||||
#include <mysql/plugin.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
/** @file ha_innodb.cc */
|
||||
|
||||
/* Include necessary InnoDB headers */
|
||||
|
@ -1172,7 +1174,28 @@ innobase_mysql_tmpfile(void)
|
|||
will be passed to fdopen(), it will be closed by invoking
|
||||
fclose(), which in turn will invoke close() instead of
|
||||
my_close(). */
|
||||
#ifdef _WIN32
|
||||
/* Note that on Windows, the integer returned by mysql_tmpfile
|
||||
has no relation to C runtime file descriptor. Here, we need
|
||||
to call my_get_osfhandle to get the HANDLE and then convert it
|
||||
to C runtime filedescriptor. */
|
||||
{
|
||||
HANDLE hFile = my_get_osfhandle(fd);
|
||||
HANDLE hDup;
|
||||
BOOL bOK =
|
||||
DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(),
|
||||
&hDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
if(bOK) {
|
||||
fd2 = _open_osfhandle((intptr_t)hDup,0);
|
||||
}
|
||||
else {
|
||||
my_osmaperr(GetLastError());
|
||||
fd2 = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
fd2 = dup(fd);
|
||||
#endif
|
||||
if (fd2 < 0) {
|
||||
DBUG_PRINT("error",("Got error %d on dup",fd2));
|
||||
my_errno=errno;
|
||||
|
|
|
@ -415,9 +415,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
|
|||
if (!share->temporary)
|
||||
error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
|
||||
FLUSH_KEEP, FLUSH_KEEP);
|
||||
#ifdef HAVE_PREAD
|
||||
|
||||
_ma_decrement_open_count(info, 1);
|
||||
#endif
|
||||
if (share->not_flushed)
|
||||
{
|
||||
share->not_flushed= 0;
|
||||
|
|
|
@ -239,7 +239,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
|
|||
break; /* Impossible */
|
||||
}
|
||||
}
|
||||
#ifdef __WIN__
|
||||
#ifdef _WIN32
|
||||
else
|
||||
{
|
||||
/*
|
||||
|
@ -521,11 +521,11 @@ int _mi_writeinfo(register MI_INFO *info, uint operation)
|
|||
share->state.update_count= info->last_loop= ++info->this_loop;
|
||||
if ((error=mi_state_info_write(share->kfile, &share->state, 1)))
|
||||
olderror=my_errno;
|
||||
#ifdef __WIN__
|
||||
#ifdef _WIN32
|
||||
if (myisam_flush)
|
||||
{
|
||||
_commit(share->kfile);
|
||||
_commit(info->dfile);
|
||||
my_sync(share->kfile,0);
|
||||
my_sync(info->dfile,0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -55,7 +55,9 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include <m_ctype.h>
|
||||
#include <mysys_err.h>
|
||||
#include <mysql/plugin.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
/** @file ha_innodb.cc */
|
||||
|
||||
/* Include necessary InnoDB headers */
|
||||
|
@ -1219,7 +1221,28 @@ innobase_mysql_tmpfile(void)
|
|||
will be passed to fdopen(), it will be closed by invoking
|
||||
fclose(), which in turn will invoke close() instead of
|
||||
my_close(). */
|
||||
#ifdef _WIN32
|
||||
/* Note that on Windows, the integer returned by mysql_tmpfile
|
||||
has no relation to C runtime file descriptor. Here, we need
|
||||
to call my_get_osfhandle to get the HANDLE and then convert it
|
||||
to C runtime filedescriptor. */
|
||||
{
|
||||
HANDLE hFile = my_get_osfhandle(fd);
|
||||
HANDLE hDup;
|
||||
BOOL bOK =
|
||||
DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(),
|
||||
&hDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
if(bOK) {
|
||||
fd2 = _open_osfhandle((intptr_t)hDup,0);
|
||||
}
|
||||
else {
|
||||
my_osmaperr(GetLastError());
|
||||
fd2 = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
fd2 = dup(fd);
|
||||
#endif
|
||||
if (fd2 < 0) {
|
||||
DBUG_PRINT("error",("Got error %d on dup",fd2));
|
||||
my_errno=errno;
|
||||
|
|
Loading…
Add table
Reference in a new issue