| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680 |
- /*
- This source file is part of the Swift System open source project
- Copyright (c) 2020 Apple Inc. and the Swift System project authors
- Licensed under Apache License v2.0 with Runtime Library Exception
- See https://swift.org/LICENSE.txt for license information
- */
- #if os(Windows)
- import ucrt
- import WinSDK
- import Synchronization
- private let _umask = Atomic<CInterop.Mode>(0o22)
- @inline(__always)
- func umask(
- _ mode: CInterop.Mode
- ) -> CInterop.Mode {
- _umask.exchange(mode, ordering: .relaxed)
- }
- @inline(__always)
- internal func open(
- _ path: UnsafePointer<CInterop.PlatformChar>, _ oflag: Int32
- ) -> CInt {
- let decodedFlags = DecodedOpenFlags(oflag)
- var saAttrs = SECURITY_ATTRIBUTES(
- nLength: DWORD(MemoryLayout<SECURITY_ATTRIBUTES>.size),
- lpSecurityDescriptor: nil,
- bInheritHandle: decodedFlags.bInheritHandle
- )
- guard let hFile = try? path.withCanonicalPathRepresentation({ path in
- CreateFileW(path,
- decodedFlags.dwDesiredAccess,
- FILE_SHARE_DELETE
- | FILE_SHARE_READ
- | FILE_SHARE_WRITE,
- &saAttrs,
- decodedFlags.dwCreationDisposition,
- decodedFlags.dwFlagsAndAttributes,
- nil)
- }), hFile != INVALID_HANDLE_VALUE else {
- ucrt._set_errno(_mapWindowsErrorToErrno(GetLastError()))
- return -1
- }
- return _open_osfhandle(intptr_t(bitPattern: hFile), oflag);
- }
- @inline(__always)
- internal func open(
- _ path: UnsafePointer<CInterop.PlatformChar>, _ oflag: Int32,
- _ mode: CInterop.Mode
- ) -> CInt {
- let actualMode = mode & ~_umask.load(ordering: .relaxed)
- guard let pSD = _createSecurityDescriptor(from: actualMode, for: .file) else {
- ucrt._set_errno(_mapWindowsErrorToErrno(GetLastError()))
- return -1
- }
- defer {
- pSD.deallocate()
- }
- let decodedFlags = DecodedOpenFlags(oflag)
- var saAttrs = SECURITY_ATTRIBUTES(
- nLength: DWORD(MemoryLayout<SECURITY_ATTRIBUTES>.size),
- lpSecurityDescriptor: pSD,
- bInheritHandle: decodedFlags.bInheritHandle
- )
- guard let hFile = try? path.withCanonicalPathRepresentation({ path in
- CreateFileW(path,
- decodedFlags.dwDesiredAccess,
- FILE_SHARE_DELETE
- | FILE_SHARE_READ
- | FILE_SHARE_WRITE,
- &saAttrs,
- decodedFlags.dwCreationDisposition,
- decodedFlags.dwFlagsAndAttributes,
- nil)
- }), hFile != INVALID_HANDLE_VALUE else {
- ucrt._set_errno(_mapWindowsErrorToErrno(GetLastError()))
- return -1
- }
- return _open_osfhandle(intptr_t(bitPattern: hFile), oflag);
- }
- @inline(__always)
- internal func close(_ fd: Int32) -> Int32 {
- _close(fd)
- }
- @inline(__always)
- internal func lseek(
- _ fd: Int32, _ off: Int64, _ whence: Int32
- ) -> Int64 {
- _lseeki64(fd, off, whence)
- }
- @inline(__always)
- internal func read(
- _ fd: Int32, _ buf: UnsafeMutableRawPointer!, _ nbyte: Int
- ) -> Int {
- Int(_read(fd, buf, numericCast(nbyte)))
- }
- @inline(__always)
- internal func write(
- _ fd: Int32, _ buf: UnsafeRawPointer!, _ nbyte: Int
- ) -> Int {
- Int(_write(fd, buf, numericCast(nbyte)))
- }
- @inline(__always)
- internal func lseek(
- _ fd: Int32, _ off: off_t, _ whence: Int32
- ) -> off_t {
- _lseek(fd, off, whence)
- }
- @inline(__always)
- internal func dup(_ fd: Int32) -> Int32 {
- _dup(fd)
- }
- @inline(__always)
- internal func dup2(_ fd: Int32, _ fd2: Int32) -> Int32 {
- // _dup2 returns 0 to indicate success.
- if _dup2(fd, fd2) == 0 {
- return fd2
- }
- return -1
- }
- @inline(__always)
- internal func pread(
- _ fd: Int32, _ buf: UnsafeMutableRawPointer!, _ nbyte: Int, _ offset: off_t
- ) -> Int {
- let handle: intptr_t = _get_osfhandle(fd)
- if handle == /* INVALID_HANDLE_VALUE */ -1 { ucrt._set_errno(EBADF); return -1 }
- // Windows ReadFile accepts DWORD (32-bit) for buffer size, so validate nbyte doesn't exceed it
- if nbyte > Int(DWORD.max) {
- ucrt._set_errno(EINVAL)
- return -1
- }
- // NOTE: this is a non-owning handle, do *not* call CloseHandle on it
- let hFile: HANDLE = HANDLE(bitPattern: handle)!
- var ovlOverlapped: OVERLAPPED = OVERLAPPED()
- ovlOverlapped.OffsetHigh = DWORD(UInt32(offset >> 32) & 0xffffffff)
- ovlOverlapped.Offset = DWORD(UInt32(offset >> 0) & 0xffffffff)
- var nNumberOfBytesRead: DWORD = 0
- if !ReadFile(hFile, buf, DWORD(nbyte), &nNumberOfBytesRead, &ovlOverlapped) {
- ucrt._set_errno(_mapWindowsErrorToErrno(GetLastError()))
- return Int(-1)
- }
- return Int(nNumberOfBytesRead)
- }
- @inline(__always)
- internal func pwrite(
- _ fd: Int32, _ buf: UnsafeRawPointer!, _ nbyte: Int, _ offset: off_t
- ) -> Int {
- let handle: intptr_t = _get_osfhandle(fd)
- if handle == /* INVALID_HANDLE_VALUE */ -1 { ucrt._set_errno(EBADF); return -1 }
- // Windows WriteFile accepts DWORD (32-bit) for buffer size, so validate nbyte doesn't exceed it
- if nbyte > Int(DWORD.max) {
- ucrt._set_errno(EINVAL)
- return -1
- }
- // NOTE: this is a non-owning handle, do *not* call CloseHandle on it
- let hFile: HANDLE = HANDLE(bitPattern: handle)!
- var ovlOverlapped: OVERLAPPED = OVERLAPPED()
- ovlOverlapped.OffsetHigh = DWORD(UInt32(offset >> 32) & 0xffffffff)
- ovlOverlapped.Offset = DWORD(UInt32(offset >> 0) & 0xffffffff)
- var nNumberOfBytesWritten: DWORD = 0
- if !WriteFile(hFile, buf, DWORD(nbyte), &nNumberOfBytesWritten,
- &ovlOverlapped) {
- ucrt._set_errno(_mapWindowsErrorToErrno(GetLastError()))
- return Int(-1)
- }
- return Int(nNumberOfBytesWritten)
- }
- @inline(__always)
- internal func pipe(
- _ fds: UnsafeMutablePointer<Int32>, bytesReserved: UInt32 = 0
- ) -> CInt {
- return _pipe(fds, bytesReserved, _O_BINARY | _O_NOINHERIT);
- }
- @inline(__always)
- internal func csystem_posix_pipe2(
- _ fds: UnsafeMutablePointer<Int32>, bytesReserved: UInt32 = 0, _ oflag: Int32
- ) -> CInt {
- return _pipe(fds, bytesReserved, _O_BINARY | oflag)
- }
- @inline(__always)
- internal func ftruncate(_ fd: Int32, _ length: off_t) -> Int32 {
- let handle: intptr_t = _get_osfhandle(fd)
- if handle == /* INVALID_HANDLE_VALUE */ -1 { ucrt._set_errno(EBADF); return -1 }
- // NOTE: this is a non-owning handle, do *not* call CloseHandle on it
- let hFile: HANDLE = HANDLE(bitPattern: handle)!
- let liDesiredLength = LARGE_INTEGER(QuadPart: LONGLONG(length))
- var liCurrentOffset = LARGE_INTEGER(QuadPart: 0)
- // Save the current position and restore it when we're done
- if !SetFilePointerEx(hFile, liCurrentOffset, &liCurrentOffset,
- FILE_CURRENT) {
- ucrt._set_errno(_mapWindowsErrorToErrno(GetLastError()))
- return -1
- }
- defer {
- _ = SetFilePointerEx(hFile, liCurrentOffset, nil, FILE_BEGIN);
- }
- // Truncate (or extend) the file
- if !SetFilePointerEx(hFile, liDesiredLength, nil, FILE_BEGIN)
- || !SetEndOfFile(hFile) {
- ucrt._set_errno(_mapWindowsErrorToErrno(GetLastError()))
- return -1
- }
- return 0;
- }
- @inline(__always)
- internal func mkdir(
- _ path: UnsafePointer<CInterop.PlatformChar>,
- _ mode: CInterop.Mode
- ) -> CInt {
- let actualMode = mode & ~_umask.load(ordering: .relaxed)
- guard let pSD = _createSecurityDescriptor(from: actualMode,
- for: .directory) else {
- ucrt._set_errno(_mapWindowsErrorToErrno(GetLastError()))
- return -1
- }
- defer {
- pSD.deallocate()
- }
- var saAttrs = SECURITY_ATTRIBUTES(
- nLength: DWORD(MemoryLayout<SECURITY_ATTRIBUTES>.size),
- lpSecurityDescriptor: pSD,
- bInheritHandle: false
- )
- guard (try? path.withCanonicalPathRepresentation({ path in CreateDirectoryW(path, &saAttrs) })) == true else {
- ucrt._set_errno(_mapWindowsErrorToErrno(GetLastError()))
- return -1
- }
- return 0;
- }
- @inline(__always)
- internal func rmdir(
- _ path: UnsafePointer<CInterop.PlatformChar>
- ) -> CInt {
- guard (try? path.withCanonicalPathRepresentation({ path in RemoveDirectoryW(path) })) == true else {
- ucrt._set_errno(_mapWindowsErrorToErrno(GetLastError()))
- return -1
- }
- return 0;
- }
- internal func _mapWindowsErrorToErrno(_ errorCode: DWORD) -> CInt {
- switch errorCode {
- case ERROR_SUCCESS:
- return 0
- case ERROR_INVALID_FUNCTION,
- ERROR_INVALID_ACCESS,
- ERROR_INVALID_DATA,
- ERROR_INVALID_PARAMETER,
- ERROR_NEGATIVE_SEEK:
- return EINVAL
- case ERROR_FILE_NOT_FOUND,
- ERROR_PATH_NOT_FOUND,
- ERROR_INVALID_DRIVE,
- ERROR_NO_MORE_FILES,
- ERROR_BAD_NETPATH,
- ERROR_BAD_NET_NAME,
- ERROR_BAD_PATHNAME,
- ERROR_FILENAME_EXCED_RANGE:
- return ENOENT
- case ERROR_TOO_MANY_OPEN_FILES:
- return EMFILE
- case ERROR_ACCESS_DENIED,
- ERROR_CURRENT_DIRECTORY,
- ERROR_LOCK_VIOLATION,
- ERROR_NETWORK_ACCESS_DENIED,
- ERROR_CANNOT_MAKE,
- ERROR_FAIL_I24,
- ERROR_DRIVE_LOCKED,
- ERROR_SEEK_ON_DEVICE,
- ERROR_NOT_LOCKED,
- ERROR_LOCK_FAILED,
- ERROR_WRITE_PROTECT...ERROR_SHARING_BUFFER_EXCEEDED:
- return EACCES
- case ERROR_INVALID_HANDLE,
- ERROR_INVALID_TARGET_HANDLE,
- ERROR_DIRECT_ACCESS_HANDLE:
- return EBADF
- case ERROR_ARENA_TRASHED,
- ERROR_NOT_ENOUGH_MEMORY,
- ERROR_INVALID_BLOCK,
- ERROR_NOT_ENOUGH_QUOTA:
- return ENOMEM
- case ERROR_BAD_ENVIRONMENT:
- return E2BIG
- case ERROR_BAD_FORMAT,
- ERROR_INVALID_STARTING_CODESEG...ERROR_INFLOOP_IN_RELOC_CHAIN:
- return ENOEXEC
- case ERROR_NOT_SAME_DEVICE:
- return EXDEV
- case ERROR_FILE_EXISTS,
- ERROR_ALREADY_EXISTS:
- return EEXIST
- case ERROR_NO_PROC_SLOTS,
- ERROR_MAX_THRDS_REACHED,
- ERROR_NESTING_NOT_ALLOWED:
- return EAGAIN
- case ERROR_BROKEN_PIPE:
- return EPIPE
- case ERROR_DISK_FULL:
- return ENOSPC
- case ERROR_WAIT_NO_CHILDREN,
- ERROR_CHILD_NOT_COMPLETE:
- return ECHILD
- case ERROR_DIR_NOT_EMPTY:
- return ENOTEMPTY
- case ERROR_NO_UNICODE_TRANSLATION:
- return EILSEQ
- default:
- return EINVAL
- }
- }
- fileprivate func rightsFromModeBits(
- _ bits: Int,
- sticky: Bool = false,
- for fileOrDirectory: _FileOrDirectory
- ) -> DWORD {
- var rights: DWORD = 0
- if (bits & 0o4) != 0 {
- rights |= (FILE_READ_ATTRIBUTES
- | FILE_READ_DATA
- | FILE_READ_EA
- | STANDARD_RIGHTS_READ
- | SYNCHRONIZE)
- }
- if (bits & 0o2) != 0 {
- rights |= (FILE_APPEND_DATA
- | FILE_WRITE_ATTRIBUTES
- | FILE_WRITE_DATA
- | FILE_WRITE_EA
- | STANDARD_RIGHTS_WRITE
- | SYNCHRONIZE)
- if fileOrDirectory == .directory && !sticky {
- rights |= FILE_DELETE_CHILD
- }
- }
- if (bits & 0o1) != 0 {
- rights |= (FILE_EXECUTE
- | FILE_READ_ATTRIBUTES
- | STANDARD_RIGHTS_EXECUTE
- | SYNCHRONIZE)
- }
- return rights
- }
- fileprivate func getTokenInformation<T>(
- of: T.Type,
- hToken: HANDLE,
- ticTokenClass: TOKEN_INFORMATION_CLASS
- ) -> UnsafePointer<T>? {
- var capacity = 1024
- for _ in 0..<2 {
- let buffer = UnsafeMutableRawPointer.allocate(
- byteCount: capacity,
- alignment: MemoryLayout<T>.alignment
- )
- var dwLength = DWORD(0)
- if GetTokenInformation(hToken,
- ticTokenClass,
- buffer,
- DWORD(capacity),
- &dwLength) {
- return UnsafePointer(buffer.assumingMemoryBound(to: T.self))
- }
- buffer.deallocate()
- capacity = Int(dwLength)
- }
- return nil
- }
- internal enum _FileOrDirectory {
- case file
- case directory
- }
- /// Build a SECURITY_DESCRIPTOR from UNIX-style "mode" bits. This only
- /// takes account of the rwx and sticky bits; there's really nothing that
- /// we can do about setuid/setgid.
- internal func _createSecurityDescriptor(from mode: CInterop.Mode,
- for fileOrDirectory: _FileOrDirectory)
- -> PSECURITY_DESCRIPTOR? {
- let ownerPerm = (Int(mode) >> 6) & 0o7
- let groupPerm = (Int(mode) >> 3) & 0o7
- let otherPerm = Int(mode) & 0o7
- let ownerRights = rightsFromModeBits(ownerPerm, for: fileOrDirectory)
- let groupRights = rightsFromModeBits(groupPerm,
- sticky: (mode & 0o1000) != 0,
- for: fileOrDirectory)
- let otherRights = rightsFromModeBits(otherPerm,
- sticky: (mode & 0o1000) != 0,
- for: fileOrDirectory)
- // If group or other permissions are *more* permissive, then we need
- // some DENY ACEs as well to implement the expected semantics
- let ownerDenyRights = ((ownerRights ^ groupRights) & groupRights) |
- ((ownerRights ^ otherRights) & otherRights)
- let groupDenyRights = (groupRights ^ otherRights) & otherRights
- var SIDAuthWorld = SID_IDENTIFIER_AUTHORITY(Value: (0, 0, 0, 0, 0, 1))
- var everyone: PSID? = nil
- guard AllocateAndInitializeSid(&SIDAuthWorld, 1,
- SECURITY_WORLD_RID,
- 0, 0, 0, 0, 0, 0, 0,
- &everyone) else {
- return nil
- }
- guard let everyone = everyone else {
- return nil
- }
- defer {
- FreeSid(everyone)
- }
- let hToken = GetCurrentThreadEffectiveToken()!
- guard let pTokenUser = getTokenInformation(of: TOKEN_USER.self,
- hToken: hToken,
- ticTokenClass: TokenUser) else {
- return nil
- }
- defer {
- pTokenUser.deallocate()
- }
- guard let pTokenPrimaryGroup = getTokenInformation(
- of: TOKEN_PRIMARY_GROUP.self,
- hToken: hToken,
- ticTokenClass: TokenPrimaryGroup
- ) else {
- return nil
- }
- defer {
- pTokenPrimaryGroup.deallocate()
- }
- let user = pTokenUser.pointee.User.Sid!
- let group = pTokenPrimaryGroup.pointee.PrimaryGroup!
- var eas = [
- EXPLICIT_ACCESS_W(
- grfAccessPermissions: ownerRights,
- grfAccessMode: GRANT_ACCESS,
- grfInheritance: NO_INHERITANCE,
- Trustee: TRUSTEE_W(
- pMultipleTrustee: nil,
- MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
- TrusteeForm: TRUSTEE_IS_SID,
- TrusteeType: TRUSTEE_IS_USER,
- ptstrName:
- user.assumingMemoryBound(to: CInterop.PlatformChar.self)
- )
- ),
- EXPLICIT_ACCESS_W(
- grfAccessPermissions: groupRights,
- grfAccessMode: GRANT_ACCESS,
- grfInheritance: NO_INHERITANCE,
- Trustee: TRUSTEE_W(
- pMultipleTrustee: nil,
- MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
- TrusteeForm: TRUSTEE_IS_SID,
- TrusteeType: TRUSTEE_IS_GROUP,
- ptstrName:
- group.assumingMemoryBound(to: CInterop.PlatformChar.self)
- )
- ),
- EXPLICIT_ACCESS_W(
- grfAccessPermissions: otherRights,
- grfAccessMode: GRANT_ACCESS,
- grfInheritance: NO_INHERITANCE,
- Trustee: TRUSTEE_W(
- pMultipleTrustee: nil,
- MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
- TrusteeForm: TRUSTEE_IS_SID,
- TrusteeType: TRUSTEE_IS_GROUP,
- ptstrName:
- everyone.assumingMemoryBound(to: CInterop.PlatformChar.self)
- )
- )
- ]
- if ownerDenyRights != 0 {
- eas.append(
- EXPLICIT_ACCESS_W(
- grfAccessPermissions: ownerDenyRights,
- grfAccessMode: DENY_ACCESS,
- grfInheritance: NO_INHERITANCE,
- Trustee: TRUSTEE_W(
- pMultipleTrustee: nil,
- MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
- TrusteeForm: TRUSTEE_IS_SID,
- TrusteeType: TRUSTEE_IS_USER,
- ptstrName:
- user.assumingMemoryBound(to: CInterop.PlatformChar.self)
- )
- )
- )
- }
- if groupDenyRights != 0 {
- eas.append(
- EXPLICIT_ACCESS_W(
- grfAccessPermissions: groupDenyRights,
- grfAccessMode: DENY_ACCESS,
- grfInheritance: NO_INHERITANCE,
- Trustee: TRUSTEE_W(
- pMultipleTrustee: nil,
- MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
- TrusteeForm: TRUSTEE_IS_SID,
- TrusteeType: TRUSTEE_IS_GROUP,
- ptstrName:
- group.assumingMemoryBound(to: CInterop.PlatformChar.self)
- )
- )
- )
- }
- var pACL: PACL? = nil
- guard SetEntriesInAclW(ULONG(eas.count),
- &eas,
- nil,
- &pACL) == ERROR_SUCCESS else {
- return nil
- }
- defer {
- LocalFree(pACL)
- }
- // Create the security descriptor, making sure that inherited ACEs don't
- // take effect, since that wouldn't match the behaviour of mode bits.
- var descriptor = SECURITY_DESCRIPTOR()
- guard InitializeSecurityDescriptor(&descriptor,
- SECURITY_DESCRIPTOR_REVISION) else {
- return nil
- }
- guard SetSecurityDescriptorControl(&descriptor,
- SE_DACL_PROTECTED,
- SE_DACL_PROTECTED)
- && SetSecurityDescriptorOwner(&descriptor, user, false)
- && SetSecurityDescriptorGroup(&descriptor, group, false)
- && SetSecurityDescriptorDacl(&descriptor,
- true,
- pACL,
- false) else {
- return nil
- }
- // Make it self-contained (up to this point it uses pointers)
- var dwRelativeSize = DWORD(0)
- guard !MakeSelfRelativeSD(&descriptor, nil, &dwRelativeSize)
- && GetLastError() == ERROR_INSUFFICIENT_BUFFER else {
- return nil
- }
- let pDescriptor = UnsafeMutableRawPointer.allocate(
- byteCount: Int(dwRelativeSize),
- alignment: MemoryLayout<SECURITY_DESCRIPTOR>.alignment
- ).assumingMemoryBound(to: SECURITY_DESCRIPTOR.self)
- guard MakeSelfRelativeSD(&descriptor, pDescriptor, &dwRelativeSize) else {
- pDescriptor.deallocate()
- return nil
- }
- return UnsafeMutableRawPointer(pDescriptor)
- }
- fileprivate struct DecodedOpenFlags {
- var dwDesiredAccess: DWORD
- var dwCreationDisposition: DWORD
- var bInheritHandle: WindowsBool
- var dwFlagsAndAttributes: DWORD
- init(_ oflag: Int32) {
- switch oflag & (_O_CREAT | _O_EXCL | _O_TRUNC) {
- case _O_CREAT | _O_EXCL, _O_CREAT | _O_EXCL | _O_TRUNC:
- dwCreationDisposition = CREATE_NEW
- case _O_CREAT:
- dwCreationDisposition = OPEN_ALWAYS
- case _O_CREAT | _O_TRUNC:
- dwCreationDisposition = CREATE_ALWAYS
- case _O_TRUNC:
- dwCreationDisposition = TRUNCATE_EXISTING
- default:
- dwCreationDisposition = OPEN_EXISTING
- }
- // The _O_RDONLY, _O_WRONLY and _O_RDWR flags are non-overlapping
- // on Windows; in particular, _O_RDONLY is zero, which means we can't
- // test for it by AND-ing.
- dwDesiredAccess = 0
- switch (oflag & (_O_RDONLY|_O_WRONLY|_O_RDWR)) {
- case _O_RDONLY:
- dwDesiredAccess |= GENERIC_READ
- case _O_WRONLY:
- dwDesiredAccess |= GENERIC_WRITE
- case _O_RDWR:
- dwDesiredAccess |= GENERIC_READ | GENERIC_WRITE
- default:
- break
- }
- bInheritHandle = WindowsBool((oflag & _O_NOINHERIT) == 0)
- dwFlagsAndAttributes = 0
- if (oflag & _O_SEQUENTIAL) != 0 {
- dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN
- }
- if (oflag & _O_RANDOM) != 0 {
- dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS
- }
- if (oflag & _O_TEMPORARY) != 0 {
- dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE
- }
- if (oflag & _O_SHORT_LIVED) != 0 {
- dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY
- } else {
- dwFlagsAndAttributes |= FILE_ATTRIBUTE_NORMAL
- }
- }
- }
- #endif
|