diff --git a/Source/IO/AuIOHandle.Unix.cpp b/Source/IO/AuIOHandle.Unix.cpp index dbd8d8fa..6fd47ae5 100644 --- a/Source/IO/AuIOHandle.Unix.cpp +++ b/Source/IO/AuIOHandle.Unix.cpp @@ -139,6 +139,8 @@ namespace Aurora::IO this->bDirectIO = true; } + int flags {}; + switch (create.eMode) { case FS::EFileOpenMode::eRead: @@ -156,25 +158,56 @@ namespace Aurora::IO if (create.bFailIfNonEmptyFile) { + #if defined(O_EXCL) + flags = O_EXCL; + #else if (AuFS::FileExists(pathex.c_str())) { SysPushErrorResourceExists("File {} already exists", create.path); return false; } + #endif } break; } }; + + flags |= create.eMode == FS::EFileOpenMode::eRead ? O_RDONLY : (O_RDWR | O_CREAT); + flags |= O_CLOEXEC; + flags |= this->bDirectIO ? O_DIRECT : 0; iFileDescriptor = ::open(pathex.c_str(), - (create.eMode == FS::EFileOpenMode::eRead ? O_RDONLY : (O_RDWR | O_CREAT)) | O_CLOEXEC | (this->bDirectIO ? O_DIRECT : 0), + flags, 0664); if (iFileDescriptor < 0) { - SysPushErrorIO("Couldn't open file: {} ({}) {}", path, pathex, errno); - return false; + if (errno == EEXIST) + { + SysPushErrorResourceExists("File {} already exists", create.path); + return false; + } + + if (errno == EISDIR) + { + flags &= ~(O_WRONLY | O_RDWR); + iFileDescriptor = ::open(pathex.c_str(), + flags, + 0664); + } + + if (errno == ENFILE) + { + SysPushErrorIOResourceFailure("low resources"); + return false; + } + + if (iFileDescriptor < 0) + { + SysPushErrorIO("Couldn't open file: {} ({}) {}", path, pathex, errno); + return false; + } } if (!FS::ApplyDumbAdvisoryLock(iFileDescriptor, create.eAdvisoryLevel))