in utils/fs/fs.c [105:196]
int FS(swopen) (const wchar_t* filename, int oflag, int shflag, int pmode)
{
/* Construct access mode. */
DWORD dwDesiredAccess = 0;
if (HAS_FLAG (oflag, _O_RDONLY))
dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES;
if (HAS_FLAG (oflag, _O_RDWR))
dwDesiredAccess |= GENERIC_WRITE | GENERIC_READ | FILE_READ_DATA |
FILE_WRITE_DATA | FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES;
if (HAS_FLAG (oflag, _O_WRONLY))
dwDesiredAccess|= GENERIC_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES;
/* Construct shared mode. */
DWORD dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
if (HAS_FLAG (shflag, _SH_DENYRW))
dwShareMode &= ~(FILE_SHARE_READ | FILE_SHARE_WRITE);
if (HAS_FLAG (shflag, _SH_DENYWR))
dwShareMode &= ~FILE_SHARE_WRITE;
if (HAS_FLAG (shflag, _SH_DENYRD))
dwShareMode &= ~FILE_SHARE_READ;
if (HAS_FLAG (pmode, _S_IWRITE))
dwShareMode |= FILE_SHARE_READ | FILE_SHARE_WRITE;
if (HAS_FLAG (pmode, _S_IREAD))
dwShareMode |= FILE_SHARE_READ;
/* Override access mode with pmode if creating file. */
if (HAS_FLAG (oflag, _O_CREAT))
{
if (HAS_FLAG (pmode, _S_IWRITE))
dwDesiredAccess |= FILE_GENERIC_WRITE;
if (HAS_FLAG (pmode, _S_IREAD))
dwDesiredAccess |= FILE_GENERIC_READ;
}
/* Create file disposition. */
DWORD dwCreationDisposition = OPEN_EXISTING;
if (HAS_FLAG (oflag, _O_CREAT))
dwCreationDisposition = OPEN_ALWAYS;
if (HAS_FLAG (oflag, (_O_CREAT | _O_EXCL)))
dwCreationDisposition = CREATE_NEW;
if (HAS_FLAG (oflag, _O_TRUNC) && !HAS_FLAG (oflag, _O_CREAT))
dwCreationDisposition = TRUNCATE_EXISTING;
/* Set file access attributes. */
DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
if (HAS_FLAG (oflag, _O_RDONLY))
dwFlagsAndAttributes |= 0; /* No special attribute. */
if (HAS_FLAG (oflag, (_O_CREAT | _O_TEMPORARY)))
dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
if (HAS_FLAG (oflag, (_O_CREAT | _O_SHORT_LIVED)))
dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY;
if (HAS_FLAG (oflag, _O_RANDOM))
dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
if (HAS_FLAG (oflag, _O_SEQUENTIAL))
dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
/* Flag is only valid on it's own. */
if (dwFlagsAndAttributes != FILE_ATTRIBUTE_NORMAL)
dwFlagsAndAttributes &= ~FILE_ATTRIBUTE_NORMAL;
/* Set security attributes. */
SECURITY_ATTRIBUTES securityAttributes;
ZeroMemory (&securityAttributes, sizeof(SECURITY_ATTRIBUTES));
securityAttributes.bInheritHandle = !(oflag & _O_NOINHERIT);
securityAttributes.lpSecurityDescriptor = NULL;
securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
wchar_t* _filename = __hs_create_device_name (filename);
if (!_filename)
return -1;
HANDLE hResult
= CreateFileW (_filename, dwDesiredAccess, dwShareMode, &securityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, NULL);
free (_filename);
if (INVALID_HANDLE_VALUE == hResult)
return -1;
/* Now we have a Windows handle, we have to convert it to an FD and apply
the remaining flags. */
const int flag_mask = _O_APPEND | _O_RDONLY | _O_TEXT | _O_WTEXT;
int fd = _open_osfhandle ((intptr_t)hResult, oflag & flag_mask);
if (-1 == fd)
return -1;
/* Finally we can change the mode to the requested one. */
const int mode_mask = _O_TEXT | _O_BINARY | _O_U16TEXT | _O_U8TEXT | _O_WTEXT;
if ((oflag & mode_mask) && (-1 == _setmode (fd, oflag & mode_mask)))
return -1;
return fd;
}