diff options
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/my_create.c | 5 | ||||
-rw-r--r-- | mysys/my_open.c | 184 |
2 files changed, 188 insertions, 1 deletions
diff --git a/mysys/my_create.c b/mysys/my_create.c index 5fa97a9ca78..a85417c7701 100644 --- a/mysys/my_create.c +++ b/mysys/my_create.c @@ -47,13 +47,16 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, #elif defined(VMS) fd = open((my_string) FileName, access_flags | O_CREAT, 0, "ctx=stm","ctx=bin"); -#elif defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2) +#elif defined(MSDOS) || defined(__EMX__) || defined(OS2) if (access_flags & O_SHARE) fd = sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY, SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); else fd = open((my_string) FileName, access_flags | O_CREAT | O_BINARY, MY_S_IREAD | MY_S_IWRITE); +#elif defined(__WIN__) + fd= my_sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY, + SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); #else fd = open(FileName, access_flags); #endif diff --git a/mysys/my_open.c b/mysys/my_open.c index 69d63c49554..baca97450b7 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -56,12 +56,18 @@ File my_open(const char *FileName, int Flags, myf MyFlags) DBUG_RETURN(my_register_filename(-1, FileName, FILE_BY_OPEN, EE_FILENOTFOUND, MyFlags)); } +#ifndef __WIN__ if (Flags & O_SHARE) fd = sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); else fd = open((my_string) FileName, Flags | O_BINARY, MY_S_IREAD | MY_S_IWRITE); +#else + fd= my_sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, + MY_S_IREAD | MY_S_IWRITE); +#endif + #elif !defined(NO_OPEN_3) fd = open(FileName, Flags, my_umask); /* Normal unix */ #else @@ -167,3 +173,181 @@ File my_register_filename(File fd, const char *FileName, enum file_type FileName, my_errno); return(fd); } + +#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)) == (HANDLE)0xffffffff) + { + /* + * 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 */ + } + + fh= _open_osfhandle((long)osfh, oflag & (_O_APPEND | _O_RDONLY | _O_TEXT)); + + return fh; /* return handle */ +} +#endif /* __WIN__ */ |