Пример #1
0
/**
  Join thread.
  This function provides combined implementation for
  pthread_join() and pthread_join_with_handle() functions.

  @param thread      reference to pthread object
  @param handle      thread handle of thread to be joined
  @return int
    @retval 0 success
    @retval 1 failure

*/
int pthread_join_base(pthread_t thread, HANDLE handle)
{
    DWORD ret;
    if(!handle)
    {
        handle = OpenThread(SYNCHRONIZE, FALSE, thread);
        if(!handle)
        {
            my_osmaperr(GetLastError());
            goto error_return;
        }
    }
    ret = WaitForSingleObject(handle, INFINITE);
    if(ret != WAIT_OBJECT_0)
    {
        my_osmaperr(GetLastError());
        goto error_return;
    }
    CloseHandle(handle);
    return 0;

error_return:
    if(handle)
        CloseHandle(handle);
    return 1;
}
Пример #2
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);
}
Пример #3
0
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 %zd", fd, Buffer, Count));
  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))
  {
    nWritten= (size_t)-1;
    my_osmaperr(GetLastError());
  }
  DBUG_RETURN((size_t)nWritten);
}
Пример #4
0
/**
  Create thread.
  This function provides combined implementation for
  pthread_create() and pthread_create_get_handle() functions.

  @param thread_id    reference to pthread object
  @param attr         reference to pthread attribute
  @param func         pthread handler function
  @param param        parameters to pass to newly created thread
  @param out_handle   reference to thread handle. This needs to be passed to
                      pthread_join_with_handle() function when it is joined
  @return int
    @retval 0 success
    @retval 1 failure

*/
int pthread_create_base(pthread_t* thread_id, const pthread_attr_t* attr, pthread_handler func, void* param, HANDLE* out_handle)
{
    HANDLE handle= NULL;
    struct thread_start_parameter* parameter;
    unsigned int stack_size;
    
    parameter = (struct thread_start_parameter*)malloc(sizeof(*parameter));
    if(!parameter)
        goto error_return;    
    parameter->func = func;
    parameter->arg = param;
    stack_size = attr?attr->dwStackSize:0;    
    handle= (HANDLE)_beginthreadex(NULL, stack_size, pthread_start, parameter, 0, thread_id);
    if(!handle)
    {
        my_osmaperr(GetLastError());
        free(parameter);
        goto error_return;
    }
    if(!out_handle)
        /* Do not need thread handle, close it */
        CloseHandle(handle);
    else
        /* Save thread handle, it will be used later during join */
        *out_handle= handle;
    return 0;
	
error_return:
    return 1;
}
Пример #5
0
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);
}
Пример #6
0
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);
}
Пример #7
0
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);
}
Пример #8
0
int my_thread_create(my_thread_handle *thread, const my_thread_attr_t *attr,
                     my_start_routine func, void *arg)
{
#ifndef _WIN32
    return pthread_create(&thread->thread, attr, func, arg);
#else
    struct thread_start_parameter *par;
    unsigned int  stack_size;

    par= (struct thread_start_parameter *)malloc(sizeof(*par));
    if (!par)
        goto error_return;

    par->func= func;
    par->arg= arg;
    stack_size= attr ? attr->dwStackSize : 0;

    thread->handle= (HANDLE)_beginthreadex(NULL, stack_size, win_thread_start,
                                           par, 0, &thread->thread);
    if (thread->handle)
        return 0;

    my_osmaperr(GetLastError());
    free(par);

error_return:
    thread->thread= 0;
    thread->handle= NULL;
    return 1;
#endif
}
Пример #9
0
int my_rename(const char *from, const char *to, myf MyFlags)
{
  int error = 0;
  DBUG_ENTER("my_rename");
  DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags));

#if defined(HAVE_FILE_VERSIONS)
  {				/* Check that there isn't a old file */
    int save_errno;
    MY_STAT my_stat_result;
    save_errno=my_errno;
    if (my_stat(to,&my_stat_result,MYF(0)))
    {
      my_errno=EEXIST;
      error= -1;
      if (MyFlags & MY_FAE+MY_WME)
      {
        char errbuf[MYSYS_STRERROR_SIZE];
        my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG), from, to,
                 my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno));
      }
      DBUG_RETURN(error);
    }
    my_errno=save_errno;
  }
#endif
#if defined(__WIN__)
  if(!MoveFileEx(from, to, MOVEFILE_COPY_ALLOWED|
                           MOVEFILE_REPLACE_EXISTING))
  {
    my_osmaperr(GetLastError());
#else
  if (rename(from,to))
  {
#endif
    my_errno=errno;
    error = -1;
    if (MyFlags & (MY_FAE+MY_WME))
    {
      char errbuf[MYSYS_STRERROR_SIZE];
      my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG), from, to,
               my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno));
    }
  }
  else if (MyFlags & MY_SYNC_DIR)
  {
#ifdef NEED_EXPLICIT_SYNC_DIR
    /* do only the needed amount of syncs: */
    char dir_from[FN_REFLEN], dir_to[FN_REFLEN];
    size_t dir_from_length, dir_to_length;
    dirname_part(dir_from, from, &dir_from_length);
    dirname_part(dir_to, to, &dir_to_length);
    if (my_sync_dir(dir_from, MyFlags) ||
        (strcmp(dir_from, dir_to) &&
         my_sync_dir(dir_to, MyFlags)))
      error= -1;
#endif
  }
  DBUG_RETURN(error);
} /* my_rename */
Пример #10
0
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();
    if(lastError == ERROR_HANDLE_EOF)
      DBUG_RETURN(0); /*return 0 at EOF*/
    my_osmaperr(lastError);
    DBUG_RETURN(-1);
  }
  DBUG_RETURN(nBytesRead);
}
Пример #11
0
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);
}
Пример #12
0
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);
}
Пример #13
0
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);
}
Пример #14
0
int my_thread_create(my_thread_handle *thread, const my_thread_attr_t *attr,
                     my_start_routine func, void *arg)
{
#ifndef _WIN32
  return pthread_create(&thread->thread, attr, func, arg);
#else
  struct thread_start_parameter *par;
  unsigned int  stack_size;

  par= (struct thread_start_parameter *)malloc(sizeof(*par));
  if (!par)
    goto error_return;

  par->func= func;
  par->arg= arg;
  stack_size= attr ? attr->dwStackSize : 0;

  thread->handle= (HANDLE)_beginthreadex(NULL, stack_size, win_thread_start,
                                         par, 0, &thread->thread);

  if (thread->handle)
  {
    /* Note that JOINABLE is default, so attr == NULL => JOINABLE. */
    if (attr && attr->detachstate == MY_THREAD_CREATE_DETACHED)
    {
      /*
        Close handles for detached threads right away to avoid leaking
        handles. For joinable threads we need the handle during
        my_thread_join. It will be closed there.
      */
      CloseHandle(thread->handle);
      thread->handle= NULL;
    }
    return 0;
  }

  my_osmaperr(GetLastError());
  free(par);

error_return:
  thread->thread= 0;
  thread->handle= NULL;
  return 1;
#endif
}
Пример #15
0
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);
}
Пример #16
0
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);
}
Пример #17
0
int my_thread_join(my_thread_handle *thread, void **value_ptr)
{
#ifndef _WIN32
    return pthread_join(thread->thread, value_ptr);
#else
    DWORD  ret;
    int  result= 0;
    ret= WaitForSingleObject(thread->handle, INFINITE);
    if (ret != WAIT_OBJECT_0)
    {
        my_osmaperr(GetLastError());
        result= 1;
    }
    if (thread->handle)
        CloseHandle(thread->handle);
    thread->thread= 0;
    thread->handle= NULL;
    return result;
#endif
}
Пример #18
0
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);
}
Пример #19
0
/* 
  Delete file.

  The function also makes best effort to minimize number of errors, 
  where another program (or thread in the current program) has the the same file
  open.

  We're using 2 tricks to prevent the errors.

  1. A usual Win32's DeleteFile() can with ERROR_SHARED_VIOLATION,
  because the file is opened in another application (often, antivirus or backup)
  
  We avoid the error by using CreateFile() with FILE_FLAG_DELETE_ON_CLOSE, instead
  of DeleteFile()

  2. If file which is deleted (delete on close) but has not entirely gone,
  because it is still opened by some app, an attempt to trcreate file with the 
  same name would  result in yet another error. The workaround here is renaming 
  a file to unique name.

  Symbolic link are deleted without renaming. Directories are not deleted.
 */
static int my_win_unlink(const char *name)
{
  HANDLE handle= INVALID_HANDLE_VALUE;
  DWORD attributes;
  DWORD last_error;
  char unique_filename[MAX_PATH + 35];
  unsigned long long tsc; /* time stamp counter, for unique filename*/

  DBUG_ENTER("my_win_unlink");
  attributes= GetFileAttributes(name);
  if (attributes == INVALID_FILE_ATTRIBUTES)
  {
    last_error= GetLastError();
    DBUG_PRINT("error",("GetFileAttributes(%s) failed with %u\n", name, last_error));
    goto error;
  }

  if (attributes & FILE_ATTRIBUTE_DIRECTORY)
  {
    DBUG_PRINT("error",("can't remove %s - it is a directory\n", name));
    errno= EINVAL;
    DBUG_RETURN(-1);
  }
 
  if (attributes & FILE_ATTRIBUTE_REPARSE_POINT)
  {
    /* Symbolic link. Delete link, the not target */
    if (!DeleteFile(name))
    {
       last_error= GetLastError();
       DBUG_PRINT("error",("DeleteFile(%s) failed with %u\n", name,last_error));
       goto error;
    }
    DBUG_RETURN(0);
  }

  handle= CreateFile(name, DELETE, 0,  NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
  if (handle != INVALID_HANDLE_VALUE)
  {
    /*
      We opened file without sharing flags (exclusive), no one else has this file
      opened, thus it is save to close handle to remove it. No renaming is 
      necessary.
    */
    CloseHandle(handle);
    DBUG_RETURN(0);
  }

  /*
     Can't open file exclusively, hence the file must be already opened by 
     someone else. Open it for delete (with all FILE_SHARE flags set), 
     rename to unique name, close.
  */
  handle= CreateFile(name, DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
    NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
  if (handle == INVALID_HANDLE_VALUE)
  {
     last_error= GetLastError();
     DBUG_PRINT("error",
       ("CreateFile(%s) with FILE_FLAG_DELETE_ON_CLOSE failed with %u\n",
        name,last_error));
     goto error;
  }

  tsc= __rdtsc();
  my_snprintf(unique_filename,sizeof(unique_filename),"%s.%llx.deleted", 
    name, tsc);
  if (!MoveFile(name, unique_filename)) 
  {
    DBUG_PRINT("warning",  ("moving %s to unique filename failed, error %u\n",
    name,GetLastError()));
  }

  CloseHandle(handle);
  DBUG_RETURN(0);
 
error:
  my_osmaperr(last_error);
  DBUG_RETURN(-1);
}
Пример #20
0
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 */
}