in lib/core/COsFileFuncs_Windows.cc [65:151]
int COsFileFuncs::open(const char* path, int oflag, TMode pmode) {
// To allow the underlying file to be renamed, we have to resort to using
// the Windows API file functions. Otherwise we can use the POSIX
// compatibility layer.
if ((oflag & RENAMABLE) == 0) {
// This is the simple case. Windows won't allow the file to be renamed
// whilst it's open.
return ::_open(path, oflag, pmode);
}
// Determine the correct access flags
DWORD desiredAccess(GENERIC_READ);
if ((oflag & RDWR) != 0) {
desiredAccess = GENERIC_READ | GENERIC_WRITE;
} else if ((oflag & WRONLY) != 0) {
desiredAccess = GENERIC_WRITE;
}
DWORD creationDisposition(0);
switch (oflag & (CREAT | EXCL | TRUNC)) {
case CREAT:
creationDisposition = OPEN_ALWAYS;
break;
case CREAT | EXCL:
case CREAT | TRUNC | EXCL:
creationDisposition = CREATE_NEW;
break;
case TRUNC:
creationDisposition = TRUNCATE_EXISTING;
break;
case TRUNC | EXCL:
// This doesn't make sense
errno = EINVAL;
return -1;
case CREAT | TRUNC:
creationDisposition = CREATE_ALWAYS;
break;
default:
creationDisposition = OPEN_EXISTING;
break;
}
DWORD attributes(FILE_ATTRIBUTE_NORMAL);
if ((oflag & CREAT) != 0 && (pmode & S_IWRITE) == 0) {
attributes = FILE_ATTRIBUTE_READONLY;
}
HANDLE handle = CreateFile(path, desiredAccess,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
0, creationDisposition, attributes, 0);
if (handle == INVALID_HANDLE_VALUE) {
switch (GetLastError()) {
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
case ERROR_INVALID_DRIVE:
case ERROR_BAD_PATHNAME:
errno = ENOENT;
break;
case ERROR_TOO_MANY_OPEN_FILES:
errno = EMFILE;
break;
case ERROR_ACCESS_DENIED:
case ERROR_NETWORK_ACCESS_DENIED:
case ERROR_LOCK_VIOLATION:
case ERROR_DRIVE_LOCKED:
errno = EACCES;
break;
case ERROR_INVALID_HANDLE:
errno = EBADF;
break;
case ERROR_NOT_ENOUGH_MEMORY:
errno = ENOMEM;
break;
case ERROR_DISK_FULL:
errno = ENOSPC;
break;
default:
errno = EINVAL;
break;
}
return -1;
}
// Convert the Windows handle to a POSIX compatibility layer file descriptor
int filteredFlags(oflag & (TEXT | RDONLY | APPEND));
return ::_open_osfhandle(reinterpret_cast<intptr_t>(handle), filteredFlags);
}