1 /* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6 
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 GNU General Public License for more details.
11 
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
15 
16 /*
17   The purpose of this file is to provide implementation of file IO routines on
18   Windows that can be thought as drop-in replacement for corresponding C runtime
19   functionality.
20 
21   Compared to Windows CRT, this one
22   - does not have the same file descriptor
23   limitation (default is 16384 and can  be increased further, whereas CRT poses
24   a hard limit of 2048 file descriptors)
25   - the file operations are not serialized
26   - positional IO pread/pwrite is ported here.
27   - no text mode for files, all IO is "binary"
28 
29   Naming convention:
30   All routines are prefixed with my_win_, e.g Posix open() is implemented with
31   my_win_open()
32 
33   Implemented are
34   - POSIX routines(e.g open, read, lseek ...)
35   - Some ANSI C stream routines (fopen, fdopen, fileno, fclose)
36   - Windows CRT equvalients (my_get_osfhandle, open_osfhandle)
37 
38   Worth to note:
39   - File descriptors used here are located in a range that is not compatible
40   with CRT on purpose. Attempt to use a file descriptor from Windows CRT library
41   range in my_win_* function will be punished with DBUG_ASSERT()
42 
43   - File streams (FILE *) are actually from the C runtime. The routines provided
44   here are useful only in scernarios that use low-level IO with my_win_fileno()
45 */
46 
47 #ifdef _WIN32
48 
49 #include "mysys_priv.h"
50 #include <share.h>
51 #include <sys/stat.h>
52 
53 /* Associates a file descriptor with an existing operating-system file handle.*/
my_open_osfhandle(HANDLE handle,int oflag)54 File my_open_osfhandle(HANDLE handle, int oflag)
55 {
56   int offset= -1;
57   uint i;
58   DBUG_ENTER("my_open_osfhandle");
59 
60   mysql_mutex_lock(&THR_LOCK_open);
61   for(i= MY_FILE_MIN; i < my_file_limit;i++)
62   {
63     if(my_file_info[i].fhandle == 0)
64     {
65       struct st_my_file_info *finfo= &(my_file_info[i]);
66       finfo->type=    FILE_BY_OPEN;
67       finfo->fhandle= handle;
68       finfo->oflag=   oflag;
69       offset= i;
70       break;
71     }
72   }
73   mysql_mutex_unlock(&THR_LOCK_open);
74   if(offset == -1)
75     errno= EMFILE; /* to many file handles open */
76   DBUG_RETURN(offset);
77 }
78 
79 
invalidate_fd(File fd)80 static void invalidate_fd(File fd)
81 {
82   DBUG_ENTER("invalidate_fd");
83   DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit);
84   my_file_info[fd].fhandle= 0;
85   DBUG_VOID_RETURN;
86 }
87 
88 
89 /* Get Windows handle for a file descriptor */
my_get_osfhandle(File fd)90 HANDLE my_get_osfhandle(File fd)
91 {
92   DBUG_ENTER("my_get_osfhandle");
93   DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit);
94   DBUG_RETURN(my_file_info[fd].fhandle);
95 }
96 
97 
my_get_open_flags(File fd)98 static int my_get_open_flags(File fd)
99 {
100   DBUG_ENTER("my_get_open_flags");
101   DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit);
102   DBUG_RETURN(my_file_info[fd].oflag);
103 }
104 
105 
106 /*
107   Open a file with sharing. Similar to _sopen() from libc, but allows managing
108   share delete on win32
109 
110   SYNOPSIS
111   my_win_sopen()
112   path    file name
113   oflag   operation flags
114   shflag  share flag
115   pmode   permission flags
116 
117   RETURN VALUE
118   File descriptor of opened file if success
119   -1 and sets errno if fails.
120 */
121 
my_win_sopen(const char * path,int oflag,int shflag,int pmode)122 File my_win_sopen(const char *path, int oflag, int shflag, int pmode)
123 {
124   int  fh;                                /* handle of opened file */
125   int mask;
126   HANDLE osfh;                            /* OS handle of opened file */
127   DWORD fileaccess;                       /* OS file access (requested) */
128   DWORD fileshare;                        /* OS file sharing mode */
129   DWORD filecreate;                       /* OS method of opening/creating */
130   DWORD fileattrib;                       /* OS file attribute flags */
131   SECURITY_ATTRIBUTES SecurityAttributes;
132 
133   DBUG_ENTER("my_win_sopen");
134 
135   if (check_if_legal_filename(path))
136   {
137     errno= EACCES;
138     DBUG_RETURN(-1);
139   }
140   SecurityAttributes.nLength= sizeof(SecurityAttributes);
141   SecurityAttributes.lpSecurityDescriptor= NULL;
142   SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);
143 
144   /* decode the access flags  */
145   switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
146     case _O_RDONLY:         /* read access */
147       fileaccess= GENERIC_READ;
148       break;
149     case _O_WRONLY:         /* write access */
150       fileaccess= GENERIC_WRITE;
151       break;
152     case _O_RDWR:           /* read and write access */
153       fileaccess= GENERIC_READ | GENERIC_WRITE;
154       break;
155     default:                /* error, bad oflag */
156       errno= EINVAL;
157       DBUG_RETURN(-1);
158   }
159 
160   /* decode sharing flags */
161   switch (shflag) {
162     case _SH_DENYRW:        /* exclusive access except delete */
163       fileshare= FILE_SHARE_DELETE;
164       break;
165     case _SH_DENYWR:        /* share read and delete access */
166       fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE;
167       break;
168     case _SH_DENYRD:        /* share write and delete access */
169       fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
170       break;
171     case _SH_DENYNO:        /* share read, write and delete access */
172       fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
173       break;
174     case _SH_DENYRWD:       /* exclusive access */
175       fileshare= 0L;
176       break;
177     case _SH_DENYWRD:       /* share read access */
178       fileshare= FILE_SHARE_READ;
179       break;
180     case _SH_DENYRDD:       /* share write access */
181       fileshare= FILE_SHARE_WRITE;
182       break;
183     case _SH_DENYDEL:       /* share read and write access */
184       fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE;
185       break;
186     default:                /* error, bad shflag */
187       errno= EINVAL;
188       DBUG_RETURN(-1);
189   }
190 
191   /* decode open/create method flags  */
192   switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
193     case 0:
194     case _O_EXCL:                   /* ignore EXCL w/o CREAT */
195       filecreate= OPEN_EXISTING;
196       break;
197 
198     case _O_CREAT:
199       filecreate= OPEN_ALWAYS;
200       break;
201 
202     case _O_CREAT | _O_EXCL:
203     case _O_CREAT | _O_TRUNC | _O_EXCL:
204       filecreate= CREATE_NEW;
205       break;
206 
207     case _O_TRUNC:
208     case _O_TRUNC | _O_EXCL:        /* ignore EXCL w/o CREAT */
209       filecreate= TRUNCATE_EXISTING;
210       break;
211 
212     case _O_CREAT | _O_TRUNC:
213       filecreate= CREATE_ALWAYS;
214       break;
215 
216     default:
217       /* this can't happen ... all cases are covered */
218       errno= EINVAL;
219       DBUG_RETURN(-1);
220   }
221 
222   /* decode file attribute flags if _O_CREAT was specified */
223   fileattrib= FILE_ATTRIBUTE_NORMAL;     /* default */
224   if (oflag & _O_CREAT)
225   {
226     _umask((mask= _umask(0)));
227 
228     if (!((pmode & ~mask) & _S_IWRITE))
229       fileattrib= FILE_ATTRIBUTE_READONLY;
230   }
231 
232   /* Set temporary file (delete-on-close) attribute if requested. */
233   if (oflag & _O_TEMPORARY)
234   {
235     fileattrib|= FILE_FLAG_DELETE_ON_CLOSE;
236     fileaccess|= DELETE;
237   }
238 
239   /* Set temporary file (delay-flush-to-disk) attribute if requested.*/
240   if (oflag & _O_SHORT_LIVED)
241     fileattrib|= FILE_ATTRIBUTE_TEMPORARY;
242 
243   /* Set sequential or random access attribute if requested. */
244   if (oflag & _O_SEQUENTIAL)
245     fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN;
246   else if (oflag & _O_RANDOM)
247     fileattrib|= FILE_FLAG_RANDOM_ACCESS;
248 
249   /* try to open/create the file  */
250   if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes,
251     filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
252   {
253     /*
254        OS call to open/create file failed! map the error, release
255        the lock, and return -1. note that it's not necessary to
256        call _free_osfhnd (it hasn't been used yet).
257     */
258     my_osmaperr(GetLastError());     /* map error */
259     DBUG_RETURN(-1);                 /* return error to caller */
260   }
261 
262   if ((fh= my_open_osfhandle(osfh,
263     oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1)
264   {
265     CloseHandle(osfh);
266   }
267 
268   DBUG_RETURN(fh);                   /* return handle */
269 }
270 
271 
my_win_open(const char * path,int flags)272 File my_win_open(const char *path, int flags)
273 {
274   DBUG_ENTER("my_win_open");
275   DBUG_RETURN(my_win_sopen((char *) path, flags | _O_BINARY, _SH_DENYNO,
276     _S_IREAD | S_IWRITE));
277 }
278 
279 
my_win_close(File fd)280 int my_win_close(File fd)
281 {
282   DBUG_ENTER("my_win_close");
283   if(CloseHandle(my_get_osfhandle(fd)))
284   {
285     invalidate_fd(fd);
286     DBUG_RETURN(0);
287   }
288   my_osmaperr(GetLastError());
289   DBUG_RETURN(-1);
290 }
291 
292 
my_win_pread(File Filedes,uchar * Buffer,size_t Count,my_off_t offset)293 size_t my_win_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset)
294 {
295   DWORD         nBytesRead;
296   HANDLE        hFile;
297   OVERLAPPED    ov= {0};
298   LARGE_INTEGER li;
299 
300   DBUG_ENTER("my_win_pread");
301 
302   if(!Count)
303     DBUG_RETURN(0);
304 #ifdef _WIN64
305   if(Count > UINT_MAX)
306     Count= UINT_MAX;
307 #endif
308 
309   hFile=         (HANDLE)my_get_osfhandle(Filedes);
310   li.QuadPart=   offset;
311   ov.Offset=     li.LowPart;
312   ov.OffsetHigh= li.HighPart;
313 
314   if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, &ov))
315   {
316     DWORD lastError= GetLastError();
317     /*
318       ERROR_BROKEN_PIPE is returned when no more data coming
319       through e.g. a command pipe in windows : see MSDN on ReadFile.
320     */
321     if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE)
322       DBUG_RETURN(0); /*return 0 at EOF*/
323     my_osmaperr(lastError);
324     DBUG_RETURN((size_t)-1);
325   }
326   DBUG_RETURN(nBytesRead);
327 }
328 
329 
my_win_read(File Filedes,uchar * Buffer,size_t Count)330 size_t my_win_read(File Filedes, uchar *Buffer, size_t Count)
331 {
332   DWORD         nBytesRead;
333   HANDLE        hFile;
334 
335   DBUG_ENTER("my_win_read");
336   if(!Count)
337     DBUG_RETURN(0);
338 #ifdef _WIN64
339   if(Count > UINT_MAX)
340     Count= UINT_MAX;
341 #endif
342 
343   hFile= (HANDLE)my_get_osfhandle(Filedes);
344 
345   if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, NULL))
346   {
347     DWORD lastError= GetLastError();
348     /*
349       ERROR_BROKEN_PIPE is returned when no more data coming
350       through e.g. a command pipe in windows : see MSDN on ReadFile.
351     */
352     if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE)
353       DBUG_RETURN(0); /*return 0 at EOF*/
354     my_osmaperr(lastError);
355     DBUG_RETURN((size_t)-1);
356   }
357   DBUG_RETURN(nBytesRead);
358 }
359 
360 
my_win_pwrite(File Filedes,const uchar * Buffer,size_t Count,my_off_t offset)361 size_t my_win_pwrite(File Filedes, const uchar *Buffer, size_t Count,
362                      my_off_t offset)
363 {
364   DWORD         nBytesWritten;
365   HANDLE        hFile;
366   OVERLAPPED    ov= {0};
367   LARGE_INTEGER li;
368 
369   DBUG_ENTER("my_win_pwrite");
370   DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count: %llu, offset: %llu",
371     Filedes, Buffer, (ulonglong)Count, (ulonglong)offset));
372 
373   if(!Count)
374     DBUG_RETURN(0);
375 
376 #ifdef _WIN64
377   if(Count > UINT_MAX)
378     Count= UINT_MAX;
379 #endif
380 
381   hFile=         (HANDLE)my_get_osfhandle(Filedes);
382   li.QuadPart=   offset;
383   ov.Offset=     li.LowPart;
384   ov.OffsetHigh= li.HighPart;
385 
386   if(!WriteFile(hFile, Buffer, (DWORD)Count, &nBytesWritten, &ov))
387   {
388     my_osmaperr(GetLastError());
389     DBUG_RETURN((size_t)-1);
390   }
391   else
392     DBUG_RETURN(nBytesWritten);
393 }
394 
395 
my_win_lseek(File fd,my_off_t pos,int whence)396 my_off_t my_win_lseek(File fd, my_off_t pos, int whence)
397 {
398   LARGE_INTEGER offset;
399   LARGE_INTEGER newpos;
400 
401   DBUG_ENTER("my_win_lseek");
402 
403   /* Check compatibility of Windows and Posix seek constants */
404   compile_time_assert(FILE_BEGIN == SEEK_SET && FILE_CURRENT == SEEK_CUR
405     && FILE_END == SEEK_END);
406 
407   offset.QuadPart= pos;
408   if(!SetFilePointerEx(my_get_osfhandle(fd), offset, &newpos, whence))
409   {
410     my_osmaperr(GetLastError());
411     newpos.QuadPart= -1;
412   }
413   DBUG_RETURN(newpos.QuadPart);
414 }
415 
416 
417 #ifndef FILE_WRITE_TO_END_OF_FILE
418 #define FILE_WRITE_TO_END_OF_FILE       0xffffffff
419 #endif
my_win_write(File fd,const uchar * Buffer,size_t Count)420 size_t my_win_write(File fd, const uchar *Buffer, size_t Count)
421 {
422   DWORD nWritten;
423   OVERLAPPED ov;
424   OVERLAPPED *pov= NULL;
425   HANDLE hFile;
426 
427   DBUG_ENTER("my_win_write");
428   DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count %llu", fd, Buffer,
429       (ulonglong)Count));
430 
431   if(!Count)
432     DBUG_RETURN(0);
433 
434 #ifdef _WIN64
435   if(Count > UINT_MAX)
436     Count= UINT_MAX;
437 #endif
438 
439   if(my_get_open_flags(fd) & _O_APPEND)
440   {
441     /*
442        Atomic append to the end of file is is done by special initialization of
443        the OVERLAPPED structure. See MSDN WriteFile documentation for more info.
444     */
445     memset(&ov, 0, sizeof(ov));
446     ov.Offset= FILE_WRITE_TO_END_OF_FILE;
447     ov.OffsetHigh= -1;
448     pov= &ov;
449   }
450 
451   hFile= my_get_osfhandle(fd);
452   if(!WriteFile(hFile, Buffer, (DWORD)Count, &nWritten, pov))
453   {
454     my_osmaperr(GetLastError());
455     DBUG_RETURN((size_t)-1);
456   }
457   DBUG_RETURN(nWritten);
458 }
459 
460 
my_win_chsize(File fd,my_off_t newlength)461 int my_win_chsize(File fd,  my_off_t newlength)
462 {
463   HANDLE hFile;
464   LARGE_INTEGER length;
465   DBUG_ENTER("my_win_chsize");
466 
467   hFile= (HANDLE) my_get_osfhandle(fd);
468   length.QuadPart= newlength;
469   if (!SetFilePointerEx(hFile, length , NULL , FILE_BEGIN))
470     goto err;
471   if (!SetEndOfFile(hFile))
472     goto err;
473   DBUG_RETURN(0);
474 err:
475   my_osmaperr(GetLastError());
476   my_errno= errno;
477   DBUG_RETURN(-1);
478 }
479 
480 
481 /* Get the file descriptor for stdin,stdout or stderr */
my_get_stdfile_descriptor(FILE * stream)482 static File my_get_stdfile_descriptor(FILE *stream)
483 {
484   HANDLE hFile;
485   DWORD nStdHandle;
486   DBUG_ENTER("my_get_stdfile_descriptor");
487 
488   if(stream == stdin)
489     nStdHandle= STD_INPUT_HANDLE;
490   else if(stream == stdout)
491     nStdHandle= STD_OUTPUT_HANDLE;
492   else if(stream == stderr)
493     nStdHandle= STD_ERROR_HANDLE;
494   else
495     DBUG_RETURN(-1);
496 
497   hFile= GetStdHandle(nStdHandle);
498   if(hFile != INVALID_HANDLE_VALUE)
499     DBUG_RETURN(my_open_osfhandle(hFile, 0));
500   DBUG_RETURN(-1);
501 }
502 
503 
my_win_fileno(FILE * file)504 File my_win_fileno(FILE *file)
505 {
506   HANDLE hFile= (HANDLE)_get_osfhandle(fileno(file));
507   int retval= -1;
508   uint i;
509 
510   DBUG_ENTER("my_win_fileno");
511 
512   for(i= MY_FILE_MIN; i < my_file_limit; i++)
513   {
514     if(my_file_info[i].fhandle == hFile)
515     {
516       retval= i;
517       break;
518     }
519   }
520   if(retval == -1)
521     /* try std stream */
522     DBUG_RETURN(my_get_stdfile_descriptor(file));
523   DBUG_RETURN(retval);
524 }
525 
526 
my_win_fopen(const char * filename,const char * type)527 FILE *my_win_fopen(const char *filename, const char *type)
528 {
529   FILE *file;
530   int flags= 0;
531   DBUG_ENTER("my_win_fopen");
532 
533   /*
534     If we are not creating, then we need to use my_access to make sure
535     the file exists since Windows doesn't handle files like "com1.sym"
536     very  well
537   */
538   if (check_if_legal_filename(filename))
539   {
540     errno= EACCES;
541     DBUG_RETURN(NULL);
542   }
543 
544   file= fopen(filename, type);
545   if(!file)
546     DBUG_RETURN(NULL);
547 
548   if(strchr(type,'a') != NULL)
549     flags= O_APPEND;
550 
551   /*
552      Register file handle in my_table_info.
553      Necessary for my_fileno()
554    */
555   if(my_open_osfhandle((HANDLE)_get_osfhandle(fileno(file)), flags) < 0)
556   {
557     fclose(file);
558     DBUG_RETURN(NULL);
559   }
560   DBUG_RETURN(file);
561 }
562 
563 
my_win_fdopen(File fd,const char * type)564 FILE * my_win_fdopen(File fd, const char *type)
565 {
566   FILE *file;
567   int crt_fd;
568   int flags= 0;
569 
570   DBUG_ENTER("my_win_fdopen");
571 
572   if(strchr(type,'a') != NULL)
573     flags= O_APPEND;
574   /* Convert OS file handle to CRT file descriptor and then call fdopen*/
575   crt_fd= _open_osfhandle((intptr_t)my_get_osfhandle(fd), flags);
576   if(crt_fd < 0)
577     file= NULL;
578   else
579     file= fdopen(crt_fd, type);
580   DBUG_RETURN(file);
581 }
582 
583 
my_win_fclose(FILE * file)584 int my_win_fclose(FILE *file)
585 {
586   File fd;
587 
588   DBUG_ENTER("my_win_fclose");
589   fd= my_fileno(file);
590   if(fd < 0)
591     DBUG_RETURN(-1);
592   if(fclose(file) < 0)
593     DBUG_RETURN(-1);
594   invalidate_fd(fd);
595   DBUG_RETURN(0);
596 }
597 
598 
599 
600 /*
601   Quick and dirty my_fstat() implementation for Windows.
602   Use CRT fstat on temporarily allocated file descriptor.
603   Patch file size, because size that fstat returns is not
604   reliable (may be outdated)
605 */
my_win_fstat(File fd,struct _stati64 * buf)606 int my_win_fstat(File fd, struct _stati64 *buf)
607 {
608   int crt_fd;
609   int retval;
610   HANDLE hFile, hDup;
611 
612   DBUG_ENTER("my_win_fstat");
613 
614   hFile= my_get_osfhandle(fd);
615   if(!DuplicateHandle( GetCurrentProcess(), hFile, GetCurrentProcess(),
616     &hDup ,0,FALSE,DUPLICATE_SAME_ACCESS))
617   {
618     my_osmaperr(GetLastError());
619     DBUG_RETURN(-1);
620   }
621   if ((crt_fd= _open_osfhandle((intptr_t)hDup,0)) < 0)
622     DBUG_RETURN(-1);
623 
624   retval= _fstati64(crt_fd, buf);
625   if(retval == 0)
626   {
627     /* File size returned by stat is not accurate (may be outdated), fix it*/
628     GetFileSizeEx(hDup, (PLARGE_INTEGER) (&(buf->st_size)));
629   }
630   _close(crt_fd);
631   DBUG_RETURN(retval);
632 }
633 
634 
635 
my_win_stat(const char * path,struct _stati64 * buf)636 int my_win_stat( const char *path, struct _stati64 *buf)
637 {
638   DBUG_ENTER("my_win_stat");
639   if(_stati64( path, buf) == 0)
640   {
641     /* File size returned by stat is not accurate (may be outdated), fix it*/
642     WIN32_FILE_ATTRIBUTE_DATA data;
643     if (GetFileAttributesEx(path, GetFileExInfoStandard, &data))
644     {
645       LARGE_INTEGER li;
646       li.LowPart=    data.nFileSizeLow;
647       li.HighPart=   data.nFileSizeHigh;
648       buf->st_size= li.QuadPart;
649     }
650     DBUG_RETURN(0);
651   }
652   DBUG_RETURN(-1);
653 }
654 
655 
656 
my_win_fsync(File fd)657 int my_win_fsync(File fd)
658 {
659   DBUG_ENTER("my_win_fsync");
660   if(FlushFileBuffers(my_get_osfhandle(fd)))
661     DBUG_RETURN(0);
662   my_osmaperr(GetLastError());
663   DBUG_RETURN(-1);
664 }
665 
666 
667 
my_win_dup(File fd)668 int my_win_dup(File fd)
669 {
670   HANDLE hDup;
671   DBUG_ENTER("my_win_dup");
672   if (DuplicateHandle(GetCurrentProcess(), my_get_osfhandle(fd),
673        GetCurrentProcess(), &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
674   {
675      DBUG_RETURN(my_open_osfhandle(hDup, my_get_open_flags(fd)));
676   }
677   my_osmaperr(GetLastError());
678   DBUG_RETURN(-1);
679 }
680 
681 #endif /*_WIN32*/
682