From ac0981ac1bf3a0d4f2b9494fa7fd8f410aeebeba Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Tue, 29 Aug 2023 01:24:52 +0100 Subject: [PATCH] [+] bool IsHandleFile(AuUInt uHandle) [+] bool IsHandleTTY(AuUInt uHandle) [+] bool IsHandlePipe(AuUInt uHandle) ...as opposed to forced IOHandle usage [+] AuIOHandle [+] AuSharedIOHandle --- Include/Aurora/IO/IOHandle.hpp | 6 + Include/Aurora/Runtime.hpp | 3 + Source/IO/AuIOHandle.NT.cpp | 434 +++++++++++++++------------------ Source/IO/AuIOHandle.Unix.cpp | 87 ++----- Source/IO/AuIOHandle.cpp | 69 ++++++ Source/IO/AuIOHandle.hpp | 7 + 6 files changed, 301 insertions(+), 305 deletions(-) diff --git a/Include/Aurora/IO/IOHandle.hpp b/Include/Aurora/IO/IOHandle.hpp index e4f06adf..1b0997c0 100644 --- a/Include/Aurora/IO/IOHandle.hpp +++ b/Include/Aurora/IO/IOHandle.hpp @@ -134,4 +134,10 @@ namespace Aurora::IO }; AUKN_SHARED_SOO_NC(IOHandle, IIOHandle, 256); + + AUKN_SYM bool IsHandleTTY(AuUInt uHandle); + + AUKN_SYM bool IsHandlePipe(AuUInt uHandle); + + AUKN_SYM bool IsHandleFile(AuUInt uHandle); } \ No newline at end of file diff --git a/Include/Aurora/Runtime.hpp b/Include/Aurora/Runtime.hpp index 75e52d1c..a8d52be1 100644 --- a/Include/Aurora/Runtime.hpp +++ b/Include/Aurora/Runtime.hpp @@ -146,6 +146,9 @@ using AuFutexCond = AuThreading::Waitables::FutexCondWaitable; template using AuTLSVariable = AuThreads::TLSVariable; +using AuIOHandle = AuIO::IOHandle; +using AuSharedIOHandle = AuSPtr; + #include "Aurora/Async/AuFutures.hpp" static bool AuIsThreadRunning() diff --git a/Source/IO/AuIOHandle.NT.cpp b/Source/IO/AuIOHandle.NT.cpp index b0646c54..43cdd363 100644 --- a/Source/IO/AuIOHandle.NT.cpp +++ b/Source/IO/AuIOHandle.NT.cpp @@ -42,310 +42,268 @@ namespace Aurora::IO struct NTIOHandle final : AFileHandle { - bool InitFromPath(HandleCreate create) override + bool InitFromPath(HandleCreate create) override; + }; + + bool NTIOHandle::InitFromPath(HandleCreate create) + { + HANDLE hFileHandle; + + DWORD dwFlags {}; + DWORD dwShare {}; + + if (create.path.empty()) { - HANDLE hFileHandle; + SysPushErrorArg("Cannot open an IO handle to the provided empty path"); + return false; + } - DWORD dwFlags {}; - DWORD dwShare {}; + if (!FS::EFileOpenModeIsValid(create.eMode)) + { + SysPushErrorParam("Invalid open mode"); + return false; + } - if (create.path.empty()) - { - SysPushErrorArg("Cannot open an IO handle to the provided empty path"); - return false; - } + if (!FS::EFileAdvisoryLockLevelIsValid(create.eAdvisoryLevel)) + { + SysPushErrorParam("Invalid lock mode"); + return false; + } - if (!FS::EFileOpenModeIsValid(create.eMode)) - { - SysPushErrorParam("Invalid open mode"); - return false; - } + auto pathex = FS::NormalizePathRet(create.path); + if (pathex.empty()) + { + SysPushErrorMemory(); + return false; + } - if (!FS::EFileAdvisoryLockLevelIsValid(create.eAdvisoryLevel)) - { - SysPushErrorParam("Invalid lock mode"); - return false; - } + auto win32Path = Locale::ConvertFromUTF8(pathex); + if (win32Path.empty()) + { + SysPushErrorMemory(); + return false; + } - auto pathex = FS::NormalizePathRet(create.path); - if (pathex.empty()) - { - SysPushErrorMemory(); - return false; - } + hFileHandle = INVALID_HANDLE_VALUE; - auto win32Path = Locale::ConvertFromUTF8(pathex); - if (win32Path.empty()) - { - SysPushErrorMemory(); - return false; - } + dwShare = FS::NtLockAdvisoryToShare(create.eAdvisoryLevel); - hFileHandle = INVALID_HANDLE_VALUE; + if (create.bAsyncHandle) + { + dwFlags |= FILE_FLAG_OVERLAPPED; + } - dwShare = FS::NtLockAdvisoryToShare(create.eAdvisoryLevel); - - if (create.bAsyncHandle) - { - dwFlags |= FILE_FLAG_OVERLAPPED; - } - - if (create.bDirectIOMode) - { - dwFlags |= FILE_FLAG_NO_BUFFERING; - this->bDirectIO = true; - } + if (create.bDirectIOMode) + { + dwFlags |= FILE_FLAG_NO_BUFFERING; + this->bDirectIO = true; + } - if (!dwFlags) + if (!dwFlags) + { + dwFlags |= FILE_ATTRIBUTE_NORMAL; + } + + switch (create.eMode) + { + case FS::EFileOpenMode::eRead: + { + hFileHandle = ::CreateFileW(win32Path.c_str(), + GENERIC_READ, + dwShare, + NULL, + OPEN_EXISTING, + dwFlags, + NULL); + + if (hFileHandle != INVALID_HANDLE_VALUE) { - dwFlags |= FILE_ATTRIBUTE_NORMAL; + this->uOSReadHandle = AuUInt64(hFileHandle); } - switch (create.eMode) + break; + } + case FS::EFileOpenMode::eReadWrite: + { + if (create.bAlwaysCreateDirTree) { - case FS::EFileOpenMode::eRead: + FS::CreateDirectories(pathex, true); + } + + if (create.bFailIfNonEmptyFile) { hFileHandle = ::CreateFileW(win32Path.c_str(), - GENERIC_READ, + GENERIC_WRITE | GENERIC_READ | DELETE, + NULL, + NULL, + CREATE_NEW, + dwFlags, + NULL); + + if (hFileHandle == INVALID_HANDLE_VALUE) + { + if (AuFS::FileExists(pathex.c_str())) + { + SysPushErrorResourceExists("File {} already exists", create.path); + return false; + } + } + } + else + { + hFileHandle = ::CreateFileW(win32Path.c_str(), + GENERIC_WRITE | GENERIC_READ | DELETE, dwShare, NULL, OPEN_EXISTING, dwFlags, NULL); - if (hFileHandle != INVALID_HANDLE_VALUE) - { - this->uOSReadHandle = AuUInt64(hFileHandle); - } - - break; - } - case FS::EFileOpenMode::eReadWrite: - { - if (create.bAlwaysCreateDirTree) - { - FS::CreateDirectories(pathex, true); - } - - if (create.bFailIfNonEmptyFile) - { - hFileHandle = ::CreateFileW(win32Path.c_str(), - GENERIC_WRITE | GENERIC_READ | DELETE, - NULL, - NULL, - CREATE_NEW, - dwFlags, - NULL); - - if (hFileHandle == INVALID_HANDLE_VALUE) - { - if (AuFS::FileExists(pathex.c_str())) - { - SysPushErrorResourceExists("File {} already exists", create.path); - return false; - } - } - } - else + if (hFileHandle == INVALID_HANDLE_VALUE) { hFileHandle = ::CreateFileW(win32Path.c_str(), GENERIC_WRITE | GENERIC_READ | DELETE, dwShare, NULL, - OPEN_EXISTING, + CREATE_NEW, dwFlags, NULL); + } + } - if (hFileHandle == INVALID_HANDLE_VALUE) + if (hFileHandle != INVALID_HANDLE_VALUE) + { + this->uOSReadHandle = AuUInt64(hFileHandle); + this->uOSWriteHandle = AuUInt64(hFileHandle); + } + + break; + } + case FS::EFileOpenMode::eWrite: + { + if (create.bAlwaysCreateDirTree) + { + FS::CreateDirectories(pathex, true); + } + + if (create.bFailIfNonEmptyFile) + { + hFileHandle = ::CreateFileW(win32Path.c_str(), + GENERIC_WRITE | DELETE, + NULL, + NULL, + CREATE_NEW, + dwFlags, + NULL); + + if (hFileHandle == INVALID_HANDLE_VALUE) + { + if (AuFS::FileExists(pathex.c_str())) { - hFileHandle = ::CreateFileW(win32Path.c_str(), - GENERIC_WRITE | GENERIC_READ | DELETE, - dwShare, - NULL, - CREATE_NEW, - dwFlags, - NULL); + SysPushErrorResourceExists("File {} already exists", create.path); + return false; } } - - if (hFileHandle != INVALID_HANDLE_VALUE) - { - this->uOSReadHandle = AuUInt64(hFileHandle); - this->uOSWriteHandle = AuUInt64(hFileHandle); - } - - break; } - case FS::EFileOpenMode::eWrite: + else { - if (create.bAlwaysCreateDirTree) - { - FS::CreateDirectories(pathex, true); - } + hFileHandle = ::CreateFileW(win32Path.c_str(), + GENERIC_WRITE | FILE_READ_ATTRIBUTES | DELETE, + dwShare, + NULL, + OPEN_EXISTING, + dwFlags, + NULL); - if (create.bFailIfNonEmptyFile) + if (hFileHandle == INVALID_HANDLE_VALUE) { hFileHandle = ::CreateFileW(win32Path.c_str(), GENERIC_WRITE | DELETE, - NULL, + dwShare, NULL, CREATE_NEW, dwFlags, NULL); - - if (hFileHandle == INVALID_HANDLE_VALUE) - { - if (AuFS::FileExists(pathex.c_str())) - { - SysPushErrorResourceExists("File {} already exists", create.path); - return false; - } - } } - else - { - hFileHandle = ::CreateFileW(win32Path.c_str(), - GENERIC_WRITE | FILE_READ_ATTRIBUTES | DELETE, - dwShare, - NULL, - OPEN_EXISTING, - dwFlags, - NULL); - - if (hFileHandle == INVALID_HANDLE_VALUE) - { - hFileHandle = ::CreateFileW(win32Path.c_str(), - GENERIC_WRITE | DELETE, - dwShare, - NULL, - CREATE_NEW, - dwFlags, - NULL); - } - } - - if (hFileHandle != INVALID_HANDLE_VALUE) - { - this->uOSWriteHandle = AuUInt64(hFileHandle); - } - - break; - } } - if (hFileHandle == INVALID_HANDLE_VALUE) + if (hFileHandle != INVALID_HANDLE_VALUE) { - SysPushErrorIO("Couldn't open: {}", create.path); - return false; + this->uOSWriteHandle = AuUInt64(hFileHandle); } - this->bIsAsync = create.bAsyncHandle; - - this->path = create.path; - - return this->IsValid(); + break; + } } - bool IsFile() override; - bool IsTTY() override; - bool IsPipe() override; - - AuOptionalEx optIsFile {}; - AuOptionalEx optIsPipe {}; - AuOptionalEx optIsTTY {}; - }; - - bool NTIOHandle::IsFile() - { - bool bIsFile {}; - DWORD dwType {}; - HANDLE hHandle {}; - - if (auto file = this->optIsFile) + if (hFileHandle == INVALID_HANDLE_VALUE) { - return file.value(); - } - - if (auto optHandle = this->GetOSHandleSafe()) - { - hHandle = (HANDLE)optHandle.value(); - } - else - { - SysPushErrorUninitialized(); + SysPushErrorIO("Couldn't open: {}", create.path); return false; } - if (!(dwType = GetFileType(hHandle))) - { - return false; - } + this->bIsAsync = create.bAsyncHandle; - bIsFile = dwType == FILE_TYPE_DISK; - this->optIsFile = bIsFile; - return bIsFile; + this->path = create.path; + + return this->IsValid(); } - bool NTIOHandle::IsTTY() - { - bool bIsTTY {}; - DWORD dwType {}; - HANDLE hHandle {}; - - if (auto file = this->optIsTTY) - { - return file.value(); - } - - if (auto optHandle = this->GetOSHandleSafe()) - { - hHandle = (HANDLE)optHandle.value(); - } - else - { - SysPushErrorUninitialized(); - return false; - } - - if (!(dwType = GetFileType(hHandle))) - { - return false; - } - - bIsTTY = dwType == FILE_TYPE_CHAR; - this->optIsTTY = bIsTTY; - return bIsTTY; - } - - bool NTIOHandle::IsPipe() + AUKN_SYM bool IsHandleTTY(AuUInt uHandle) { bool bIsPipe {}; DWORD dwType {}; - HANDLE hHandle {}; - if (auto file = this->optIsPipe) - { - return file.value(); - } - - if (auto optHandle = this->GetOSHandleSafe()) - { - hHandle = (HANDLE)optHandle.value(); - } - else - { - SysPushErrorUninitialized(); - return false; - } - - if (!(dwType = GetFileType(hHandle))) + if (!uHandle || + uHandle == (AuUInt)INVALID_HANDLE_VALUE) { return false; } - bIsPipe = dwType == FILE_TYPE_PIPE; - this->optIsPipe = bIsPipe; - return bIsPipe; + if (!(dwType = ::GetFileType((HANDLE)uHandle))) + { + return {}; + } + + return dwType == FILE_TYPE_CHAR; + } + + AUKN_SYM bool IsHandlePipe(AuUInt uHandle) + { + bool bIsPipe {}; + DWORD dwType {}; + + if (!uHandle || + uHandle == (AuUInt)INVALID_HANDLE_VALUE) + { + return false; + } + + if (!(dwType = ::GetFileType((HANDLE)uHandle))) + { + return {}; + } + + return dwType == FILE_TYPE_PIPE; + } + + AUKN_SYM bool IsHandleFile(AuUInt uHandle) + { + bool bIsPipe {}; + DWORD dwType {}; + + if (!uHandle || + uHandle == (AuUInt)INVALID_HANDLE_VALUE) + { + return false; + } + + if (!(dwType = ::GetFileType((HANDLE)uHandle))) + { + return {}; + } + + return dwType == FILE_TYPE_DISK; } AUKN_SYM IIOHandle *IOHandleNew() diff --git a/Source/IO/AuIOHandle.Unix.cpp b/Source/IO/AuIOHandle.Unix.cpp index 7ddef3ba..f2a0dd00 100644 --- a/Source/IO/AuIOHandle.Unix.cpp +++ b/Source/IO/AuIOHandle.Unix.cpp @@ -55,10 +55,6 @@ namespace Aurora::IO bool IsFile() override; bool IsTTY() override; bool IsPipe() override; - - AuOptionalEx optIsFile {}; - AuOptionalEx optIsPipe {}; - AuOptionalEx optIsTTY {}; }; bool UnixIOHandle::InitFromPath(HandleCreate create) @@ -178,93 +174,50 @@ namespace Aurora::IO return this->IsValid(); } - bool UnixIOHandle::IsFile() + AUKN_SYM bool IsHandleTTY(AuUInt uHandle) { - bool bIsFile {}; - struct stat st; - int iFileDescriptor {}; - - if (auto file = this->optIsFile) + if ((AuInt)uHandle < 0) { - return file.value(); - } - - if (auto optHandle = this->GetOSHandleSafe()) - { - iFileDescriptor = (int)optHandle.value(); - } - else - { - SysPushErrorUninitialized(); return false; } - if (::fstat(iFileDescriptor, &st) != 0) + return ::isatty((int)uHandle); + } + + AUKN_SYM bool IsHandlePipe(AuUInt uHandle) + { + struct stat st; + + if ((AuInt)uHandle < 0) + { + return false; + } + + if (::fstat((int)uHandle, &st) != 0) { SysPushErrorIO("fstat failed"); return false; } - bIsFile = S_ISREG(st.st_mode); - this->optIsFile = bIsFile; - return bIsFile; + return S_ISFIFO(st.st_mode); } - bool UnixIOHandle::IsTTY() + AUKN_SYM bool IsHandleFile(AuUInt uHandle) { - bool bIsTTY {}; - int iFileDescriptor {}; - - if (auto file = this->optIsTTY) - { - return file.value(); - } - - if (auto optHandle = this->GetOSHandleSafe()) - { - iFileDescriptor = (int)optHandle.value(); - } - else - { - SysPushErrorUninitialized(); - return false; - } - - bIsTTY = ::isatty(iFileDescriptor); - this->optIsTTY = bIsTTY; - return bIsTTY; - } - - bool UnixIOHandle::IsPipe() - { - bool bIsPipe {}; struct stat st; - int iFileDescriptor {}; - if (auto file = this->optIsPipe) + if ((AuInt)uHandle < 0) { - return file.value(); - } - - if (auto optHandle = this->GetOSHandleSafe()) - { - iFileDescriptor = (int)optHandle.value(); - } - else - { - SysPushErrorUninitialized(); return false; } - if (::fstat(iFileDescriptor, &st) != 0) + if (::fstat((int)uHandle, &st) != 0) { SysPushErrorIO("fstat failed"); return false; } - bIsPipe = S_ISFIFO(st.st_mode); - this->optIsPipe = bIsPipe; - return bIsPipe; + return S_ISREG(st.st_mode); } AUKN_SYM IIOHandle *IOHandleNew() diff --git a/Source/IO/AuIOHandle.cpp b/Source/IO/AuIOHandle.cpp index 8bc73077..80a72626 100644 --- a/Source/IO/AuIOHandle.cpp +++ b/Source/IO/AuIOHandle.cpp @@ -126,6 +126,75 @@ namespace Aurora::IO return true; } + bool AFileHandle::IsFile() + { + bool bIsFile {}; + + if (auto optFile = this->optIsFile) + { + return optFile.value(); + } + + if (auto optHandle = this->GetOSHandleSafe()) + { + bIsFile = IsHandleFile(optHandle.value()); + } + else + { + SysPushErrorUninitialized(); + return false; + } + + this->optIsFile = bIsFile; + return bIsFile; + } + + bool AFileHandle::IsTTY() + { + bool bIsTTY {}; + + if (auto optTTY = this->optIsTTY) + { + return optTTY.value(); + } + + if (auto optHandle = this->GetOSHandleSafe()) + { + bIsTTY = IsHandleTTY(optHandle.value()); + } + else + { + SysPushErrorUninitialized(); + return false; + } + + this->optIsTTY = bIsTTY; + return bIsTTY; + } + + bool AFileHandle::IsPipe() + { + bool bIsPipe {}; + + if (auto optPipe = this->optIsPipe) + { + return optPipe.value(); + } + + if (auto optHandle = this->GetOSHandleSafe()) + { + bIsPipe = IsHandlePipe(optHandle.value()); + } + else + { + SysPushErrorUninitialized(); + return false; + } + + this->optIsPipe = bIsPipe; + return bIsPipe; + } + AuOptionalEx AFileHandle::GetOSHandleSafe() { if (auto write = this->uOSWriteHandle) diff --git a/Source/IO/AuIOHandle.hpp b/Source/IO/AuIOHandle.hpp index d26b6a7b..903690b4 100644 --- a/Source/IO/AuIOHandle.hpp +++ b/Source/IO/AuIOHandle.hpp @@ -50,6 +50,10 @@ namespace Aurora::IO AuString GetPath() override; + bool IsFile() override; + bool IsTTY() override; + bool IsPipe() override; + AuOptionalEx uOSWriteHandle; AuOptionalEx uOSReadHandle; AuSPtr pThat; @@ -57,6 +61,9 @@ namespace Aurora::IO AuString path; IPC::IPCPipeImpl *pIPCPipe {}; bool bDirectIO {}; + AuOptionalEx optIsFile; + AuOptionalEx optIsPipe; + AuOptionalEx optIsTTY; protected: // Implement me: