diff --git a/Include/Aurora/Compression/Compression.hpp b/Include/Aurora/Compression/Compression.hpp index a22098f2..c2c57b1e 100644 --- a/Include/Aurora/Compression/Compression.hpp +++ b/Include/Aurora/Compression/Compression.hpp @@ -22,6 +22,8 @@ // Utility #include "BasicCompression.hpp" +#include "CompressionInterceptor.hpp" + // TODO: neat comment + real world data diff --git a/Include/Aurora/Compression/CompressionInterceptor.hpp b/Include/Aurora/Compression/CompressionInterceptor.hpp new file mode 100644 index 00000000..8c68e98a --- /dev/null +++ b/Include/Aurora/Compression/CompressionInterceptor.hpp @@ -0,0 +1,21 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: CompressionInterceptor.hpp + Date: 2022-9-14 + Author: Reece +***/ +#pragma once + +#include + +namespace Aurora::Compression +{ + struct ICompressionInterceptor : IO::Protocol::IProtocolInterceptorEx + { + virtual bool HasFailed() = 0; + }; + + AUKN_SYM AuSPtr NewDecompressionInterceptor(const DecompressInfo &info); + AUKN_SYM AuSPtr NewCompressionInterceptor(const CompressInfo &info); +} \ No newline at end of file diff --git a/Include/Aurora/Crypto/AES/AES.hpp b/Include/Aurora/Crypto/AES/AES.hpp index 89980695..0024cade 100644 --- a/Include/Aurora/Crypto/AES/AES.hpp +++ b/Include/Aurora/Crypto/AES/AES.hpp @@ -9,6 +9,29 @@ namespace Aurora::Crypto::AES { + /** + * @brief + * @param pContext + * @param memoryView + * @return + */ + AUKN_SYM bool CBCEncrypt(const AuSPtr pContext, + const Memory::MemoryViewWrite &memoryView); + + /** + * @brief + * @param pContext + * @param memoryView + * @return + */ + AUKN_SYM bool CBCDecrypt(const AuSPtr pContext, + const Memory::MemoryViewWrite &memoryView); + + /** + * @brief + * @param plainText + * @return + */ AUKN_SYM AuUInt GetSafeCipherPadding(const Memory::MemoryViewRead &plainText); // Remember: AES works in chunks of 128 bits diff --git a/Include/Aurora/Crypto/CBC/CBC.hpp b/Include/Aurora/Crypto/CBC/CBC.hpp new file mode 100644 index 00000000..5f2fba62 --- /dev/null +++ b/Include/Aurora/Crypto/CBC/CBC.hpp @@ -0,0 +1,23 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: CBC.hpp + Date: 2022-10-08 + Author: Reece +***/ +#pragma once + +namespace Aurora::Crypto::CBC +{ + struct ICBCContext + { + virtual bool Initialize(const Memory::MemoryViewRead &key, + const Memory::MemoryViewRead &iv) = 0; + + virtual bool GetIV(const Memory::MemoryViewWrite &writeView) = 0; + + virtual bool SetIV(const Memory::MemoryViewRead &readView) = 0; + }; + + AUKN_SHARED_API(NewContext, ICBCContext); +} \ No newline at end of file diff --git a/Include/Aurora/Crypto/Crypto.hpp b/Include/Aurora/Crypto/Crypto.hpp index 4365ce32..33ef4786 100644 --- a/Include/Aurora/Crypto/Crypto.hpp +++ b/Include/Aurora/Crypto/Crypto.hpp @@ -28,8 +28,13 @@ namespace Aurora::Crypto #else #include #endif + #include "EKeyType.hpp" #include "EPaddingType.hpp" + +#include "CBC/CBC.hpp" +#include "TDES/TDES.hpp" +#include "PBKDF2/PBKDF2.hpp" #include "AES/AES.hpp" #include "X509/X509.hpp" #include "CA/CA.hpp" diff --git a/Include/Aurora/Crypto/PBKDF2/PBKDF2.hpp b/Include/Aurora/Crypto/PBKDF2/PBKDF2.hpp new file mode 100644 index 00000000..576bbb5e --- /dev/null +++ b/Include/Aurora/Crypto/PBKDF2/PBKDF2.hpp @@ -0,0 +1,17 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: PBKDF2.hpp + Date: 2022-10-08 + Author: Reece +***/ +#pragma once + +namespace Aurora::Crypto::PBKDF2 +{ + AUKN_SYM bool PBKDF2(const Memory::MemoryViewRead &salt, + const Memory::MemoryViewRead &password, + Hashing::EHashType hashType, + AuUInt32 uIterations, + const Memory::MemoryViewWrite &out); +} \ No newline at end of file diff --git a/Include/Aurora/Crypto/TDES/TDES.hpp b/Include/Aurora/Crypto/TDES/TDES.hpp new file mode 100644 index 00000000..3ecf0931 --- /dev/null +++ b/Include/Aurora/Crypto/TDES/TDES.hpp @@ -0,0 +1,29 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: TDES.hpp + Date: 2022-10-08 + Author: Reece +***/ +#pragma once + +namespace Aurora::Crypto::TDES +{ + /** + * @brief + * @param pContext + * @param memoryView + * @return + */ + AUKN_SYM bool CBCEncrypt(const AuSPtr pContext, + const Memory::MemoryViewWrite &memoryView); + + /** + * @brief + * @param pContext + * @param memoryView + * @return + */ + AUKN_SYM bool CBCDecrypt(const AuSPtr pContext, + const Memory::MemoryViewWrite &memoryView); +} \ No newline at end of file diff --git a/Include/Aurora/IO/FS/FS.hpp b/Include/Aurora/IO/FS/FS.hpp index 769355e2..d0f2d0de 100644 --- a/Include/Aurora/IO/FS/FS.hpp +++ b/Include/Aurora/IO/FS/FS.hpp @@ -30,6 +30,20 @@ namespace Aurora::IO::FS */ AUKN_SYM AuSPtr ReadDir(const AuString &directory); + /** + * @brief + * @param string + * @return + */ + AUKN_SYM AuSPtr ReadDirRecursive(const AuString &string); + + /** + * @brief Recursively deletes any given path + * @param string + * @return + */ + AUKN_SYM bool DirDeleter(const AuString &string); + /** * @brief Writes a blob into a file chunk-by-chunk. * The directory structure may or may not exist for the write operation to succeed. diff --git a/Source/AuCrypto.cpp b/Source/AuCrypto.cpp index d29991e3..354b9da9 100644 --- a/Source/AuCrypto.cpp +++ b/Source/AuCrypto.cpp @@ -37,6 +37,7 @@ namespace Crypto gHashRMD320 = register_hash(&rmd320_desc); gPrngYarrow = register_prng(&yarrow_desc); gAesCipher = register_cipher(&aes_desc); + gDesCipher = register_cipher(&des3_desc); } static void MBedTlsInit() diff --git a/Source/AuCrypto.hpp b/Source/AuCrypto.hpp index 0bfbfcf4..4fc9ea27 100644 --- a/Source/AuCrypto.hpp +++ b/Source/AuCrypto.hpp @@ -10,6 +10,7 @@ namespace Crypto { inline int gAesCipher; + inline int gDesCipher; inline int gHashTiger; inline int gHashSha1; inline int gHashMD4; diff --git a/Source/Compression/CompressionInterceptor.cpp b/Source/Compression/CompressionInterceptor.cpp new file mode 100644 index 00000000..d6492fd1 --- /dev/null +++ b/Source/Compression/CompressionInterceptor.cpp @@ -0,0 +1,126 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: CompressionInterceptor.cpp + Date: 2022-9-14 + Author: Reece +***/ +#include +#include "Compression.hpp" +#include "BaseStream.hpp" +#include "CompressionInterceptor.hpp" + +namespace Aurora::Compression +{ + CompressionInterceptor::CompressionInterceptor() + { + + } + + void CompressionInterceptor::Init(const AuSPtr &pStream, + const AuSPtr &pBaseStream) + { + this->pBaseStream_ = pBaseStream; + this->pStream_ = pStream; + } + + IO::EStreamError CompressionInterceptor::IsOpen() + { + return IO::EStreamError::eErrorNone; + } + + IO::EStreamError CompressionInterceptor::Read(const Memory::MemoryViewStreamWrite ¶meters) + { + if (auto pBuffer = this->pLastBuffer_.lock()) + { + parameters.outVariable = pBuffer->Read(parameters.ptr, parameters.length); + return parameters.outVariable == 0 ? IO::EStreamError::eErrorEndOfStream : IO::EStreamError::eErrorNone; + } + + return IO::EStreamError::eErrorStreamNotOpen; + } + + void CompressionInterceptor::Close() + { + } + + bool CompressionInterceptor::HasFailed() + { + return this->bErrorFlag_; + } + + bool CompressionInterceptor::OnDataAvailable(const AuSPtr &pReadInByteBuffer, + const AuSPtr &pWriteOutByteBuffer) + { + this->pLastBuffer_ = pReadInByteBuffer; + this->pBaseStream_->SetBuffer(pWriteOutByteBuffer); + + bool bSuccess { true }; + do + { + auto uReadable = pReadInByteBuffer->GetNextLinearRead(); + if (!uReadable) + { + break; + } + + auto [a, b] = this->pBaseStream_->Ingest(uReadable); + bSuccess = a != 0; + } + while (bSuccess); + + if (!bSuccess) + { + this->bErrorFlag_ = true; + } + + this->pBaseStream_->SetBuffer({}); + return true; + } + + AUKN_SYM AuSPtr NewDecompressionInterceptor(const DecompressInfo &info) + { + auto pInterceptor = AuMakeShared(); + if (!pInterceptor) + { + SysPushErrorMemory(); + return {}; + } + + auto pDecompressor = DecompressorShared(AuUnsafeRaiiToShared(pInterceptor.get()), + info); + if (!pDecompressor) + { + SysPushErrorMemory(); + return {}; + } + + pInterceptor->Init(pDecompressor, + AuStaticCast(pDecompressor)); + + return pInterceptor; + } + + AUKN_SYM AuSPtr NewCompressionInterceptor(const CompressInfo &info) + { + auto pInterceptor = AuMakeShared(); + if (!pInterceptor) + { + SysPushErrorMemory(); + return {}; + } + + auto pCompressor = CompressorShared(AuUnsafeRaiiToShared(pInterceptor.get()), + info); + if (!pCompressor) + { + SysPushErrorMemory(); + return {}; + } + + pInterceptor->Init(pCompressor, + AuStaticCast(pCompressor)); + + return pInterceptor; + } +} \ No newline at end of file diff --git a/Source/Compression/CompressionInterceptor.hpp b/Source/Compression/CompressionInterceptor.hpp new file mode 100644 index 00000000..00ebfd3c --- /dev/null +++ b/Source/Compression/CompressionInterceptor.hpp @@ -0,0 +1,38 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: CompressionInterceptor.hpp + Date: 2022-9-14 + Author: Reece +***/ +#pragma once + +#include + +namespace Aurora::Compression +{ + struct CompressionInterceptor : ICompressionInterceptor, IO::IStreamReader + { + CompressionInterceptor(); + + void Init(const AuSPtr &pStream, + const AuSPtr &pBaseStream); + + bool OnDataAvailable(const AuSPtr &pReadInByteBuffer, + const AuSPtr &pWriteOutByteBuffer) override; + + inline virtual IO::EStreamError IsOpen() override; + + inline virtual IO::EStreamError Read(const Memory::MemoryViewStreamWrite ¶meters) override; + + inline virtual void Close() override; + + bool HasFailed() override; + + private: + bool bErrorFlag_ {}; + AuSPtr pStream_; + AuSPtr pBaseStream_; + AuWPtr pLastBuffer_; + }; +} \ No newline at end of file diff --git a/Source/Crypto/AES/Aes.cpp b/Source/Crypto/AES/Aes.cpp index ca744f1e..af5f155e 100644 --- a/Source/Crypto/AES/Aes.cpp +++ b/Source/Crypto/AES/Aes.cpp @@ -10,9 +10,48 @@ #include "Aes.hpp" #include #include +#include "../CBC/CBC.hpp" namespace Aurora::Crypto::AES { + AUKN_SYM bool CBCEncrypt(const AuSPtr pContext, + const Memory::MemoryViewWrite &memoryView) + { + if (!pContext) + { + SysPushErrorArg(); + return false; + } + + if (!memoryView.ptr) + { + SysPushErrorArg(); + return false; + } + + return AuStaticCast(pContext)->Encrypt(::Crypto::gAesCipher, + memoryView); + } + + AUKN_SYM bool CBCDecrypt(const AuSPtr pContext, + const Memory::MemoryViewWrite &memoryView) + { + if (!pContext) + { + SysPushErrorArg(); + return false; + } + + if (!memoryView.ptr) + { + SysPushErrorArg(); + return false; + } + + return AuStaticCast(pContext)->Decrypt(::Crypto::gAesCipher, + memoryView); + } + AUKN_SYM AuUInt GetSafeCipherPadding(const Memory::MemoryViewRead ¶meters) { auto tptr = reinterpret_cast(parameters.ptr); diff --git a/Source/Crypto/CBC/CBC.cpp b/Source/Crypto/CBC/CBC.cpp new file mode 100644 index 00000000..c24f0ab8 --- /dev/null +++ b/Source/Crypto/CBC/CBC.cpp @@ -0,0 +1,165 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: CBC.cpp + Date: 2022-10-08 + Author: Reece +***/ +#include +#include "../Crypto.hpp" +#include "CBC.hpp" + +namespace Aurora::Crypto::CBC +{ + bool CBCContext::Initialize(const Memory::MemoryViewRead &key, + const Memory::MemoryViewRead &iv) + { + if (iv.length > 32) + { + SysPushErrorArg(); + return false; + } + + if (!iv.ptr) + { + SysPushErrorArg(); + return false; + } + + if (!key.ptr) + { + SysPushErrorArg(); + return false; + } + + if (key.length > AuArraySize(this->streamKey_)) + { + SysPushErrorArg(); + return false; + } + + AuMemcpy(this->cbc_.IV, iv.ptr, iv.length); + this->iIVLength = iv.length; + this->iKeyLength = key.length; + + AuMemcpy(this->streamKey_, key.ptr, key.length); + return true; + } + + bool CBCContext::GetIV(const Memory::MemoryViewWrite &writeView) + { + if (!writeView.ptr) + { + SysPushErrorArg(); + return false; + } + + if (writeView.length != this->cbc_.blocklen) + { + return {}; + } + + AuMemcpy(writeView.ptr, this->cbc_.IV, this->cbc_.blocklen); + return true; + } + + bool CBCContext::SetIV(const Memory::MemoryViewRead &readView) + { + if (!readView.ptr) + { + SysPushErrorArg(); + return false; + } + + if (readView.length != this->cbc_.blocklen) + { + return {}; + } + + AuMemcpy(this->cbc_.IV, readView.ptr, this->cbc_.blocklen); + return true; + } + + bool CBCContext::TryInit(int iCipher) + { + char iv[32]; + int iRet {}; + + if (this->iLastCipher_ != -1) + { + return this->iLastCipher_ == iCipher; + } + + AuMemcpy(iv, this->cbc_.IV, 32); + + iRet = ::cbc_start(iCipher, + AuReinterpretCast(iv), + AuReinterpretCast(this->streamKey_), + this->iKeyLength, + 0, + &this->cbc_); + if (iRet != CRYPT_OK) + { + SysPushErrorCrypt("{}", iRet); + return {}; + } + + this->iLastCipher_ = iCipher; + return true; + } + + bool CBCContext::Decrypt(int iCipher, + const Memory::MemoryViewWrite &memoryView) + { + int iRet {}; + if (!TryInit(iCipher)) + { + return false; + } + + iRet = ::cbc_decrypt(AuReinterpretCast(memoryView.ptr), + AuReinterpretCast(memoryView.ptr), + memoryView.length, + &this->cbc_); + if (iRet != CRYPT_OK) + { + SysPushErrorCrypt("{}", iRet); + return false; + } + + return true; + } + + bool CBCContext::Encrypt(int iCipher, + const Memory::MemoryViewWrite &memoryView) + { + int iRet {}; + + if (!TryInit(iCipher)) + { + return false; + } + + iRet = ::cbc_encrypt(AuReinterpretCast(memoryView.ptr), + AuReinterpretCast(memoryView.ptr), + memoryView.length, + &this->cbc_); + if (iRet != CRYPT_OK) + { + SysPushErrorCrypt("{}", iRet); + return false; + } + + return true; + } + + AUKN_SYM ICBCContext *NewContextNew() + { + return _new CBCContext(); + } + + AUKN_SYM void NewContextRelease(ICBCContext *pContext) + { + AuSafeDelete(pContext); + } +} \ No newline at end of file diff --git a/Source/Crypto/CBC/CBC.hpp b/Source/Crypto/CBC/CBC.hpp new file mode 100644 index 00000000..3ccfff17 --- /dev/null +++ b/Source/Crypto/CBC/CBC.hpp @@ -0,0 +1,31 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: CBC.hpp + Date: 2022-10-08 + Author: Reece +***/ +#pragma once + +namespace Aurora::Crypto::CBC +{ + struct CBCContext : ICBCContext + { + bool Initialize(const Memory::MemoryViewRead &key, + const Memory::MemoryViewRead &iv) override; + + bool GetIV(const Memory::MemoryViewWrite &writeView) override; + bool SetIV(const Memory::MemoryViewRead &readView) override; + + bool TryInit(int iCipher); + + bool Decrypt(int iCipher, const Memory::MemoryViewWrite &memoryView); + bool Encrypt(int iCipher, const Memory::MemoryViewWrite &memoryView); + private: + symmetric_CBC cbc_ {}; + char streamKey_[32]; + int iKeyLength {}; + int iIVLength {}; + int iLastCipher_ { -1 }; + }; +} \ No newline at end of file diff --git a/Source/Crypto/PBKDF2/PBKDF2.cpp b/Source/Crypto/PBKDF2/PBKDF2.cpp new file mode 100644 index 00000000..89c04d0d --- /dev/null +++ b/Source/Crypto/PBKDF2/PBKDF2.cpp @@ -0,0 +1,29 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: PBKDF2.cpp + Date: 2022-10-08 + Author: Reece +***/ +#include +#include "../Crypto.hpp" + +namespace Aurora::Crypto::PBKDF2 +{ + AUKN_SYM bool PBKDF2(const Memory::MemoryViewRead &salt, + const Memory::MemoryViewRead &password, + Hashing::EHashType hashType, + AuUInt32 uIterations, + const Memory::MemoryViewWrite &out) + { + unsigned long len = out.length; + return ::pkcs_5_alg2(password.Begin(), + password.length, + salt.Begin(), + salt.length, + uIterations, + ::Crypto::HashMethodToId(hashType), + out.Begin(), + &len) == CRYPT_OK && len == out.length; + } +} \ No newline at end of file diff --git a/Source/Crypto/PBKDF2/PBKDF2.hpp b/Source/Crypto/PBKDF2/PBKDF2.hpp new file mode 100644 index 00000000..92c2adb0 --- /dev/null +++ b/Source/Crypto/PBKDF2/PBKDF2.hpp @@ -0,0 +1,9 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: PBKDF2.hpp + Date: 2022-10-08 + Author: Reece +***/ +#pragma once + diff --git a/Source/Crypto/TDES/TDES.cpp b/Source/Crypto/TDES/TDES.cpp new file mode 100644 index 00000000..77040696 --- /dev/null +++ b/Source/Crypto/TDES/TDES.cpp @@ -0,0 +1,52 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: TDES.cpp + Date: 2022-10-08 + Author: Reece +***/ +#include +#include "../Crypto.hpp" +#include "TDES.hpp" +#include "../CBC/CBC.hpp" + +namespace Aurora::Crypto::TDES +{ + AUKN_SYM bool CBCEncrypt(const AuSPtr pContext, + const Memory::MemoryViewWrite &memoryView) + { + if (!pContext) + { + SysPushErrorArg(); + return false; + } + + if (!memoryView.ptr) + { + SysPushErrorArg(); + return false; + } + + return AuStaticCast(pContext)->Encrypt(::Crypto::gDesCipher, + memoryView); + } + + AUKN_SYM bool CBCDecrypt(const AuSPtr pContext, + const Memory::MemoryViewWrite &memoryView) + { + if (!pContext) + { + SysPushErrorArg(); + return false; + } + + if (!memoryView.ptr) + { + SysPushErrorArg(); + return false; + } + + return AuStaticCast(pContext)->Decrypt(::Crypto::gDesCipher, + memoryView); + } +} \ No newline at end of file diff --git a/Source/Crypto/TDES/TDES.hpp b/Source/Crypto/TDES/TDES.hpp new file mode 100644 index 00000000..75ea6915 --- /dev/null +++ b/Source/Crypto/TDES/TDES.hpp @@ -0,0 +1,9 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: TDES.hpp + Date: 2022-10-08 + Author: Reece +***/ +#pragma once + diff --git a/Source/Debug/Stack.Win32.cpp b/Source/Debug/Stack.Win32.cpp index cdfe00d7..f30bd1d1 100644 --- a/Source/Debug/Stack.Win32.cpp +++ b/Source/Debug/Stack.Win32.cpp @@ -122,8 +122,13 @@ namespace Aurora::Debug StackTrace PlatformWalkCallStack() { StackTrace ret; - CONTEXT ctx; - if (!GetThreadContext(GetCurrentThread(), &ctx)) return {}; + CONTEXT ctx {}; + ctx.ContextFlags = CONTEXT_ALL; + if (!GetThreadContext(GetCurrentThread(), &ctx)) + { + return {}; + } + ParseStack(&ctx, ret); return ret; } diff --git a/Source/IO/FS/DirDeleter.cpp b/Source/IO/FS/DirDeleter.cpp new file mode 100644 index 00000000..157e1fee --- /dev/null +++ b/Source/IO/FS/DirDeleter.cpp @@ -0,0 +1,121 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: DirDeleter.cpp + Date: 2022-11-06 + Author: Reece +***/ +#include +#include "FS.hpp" + +namespace Aurora::IO::FS +{ + struct RecursiveDirDeleter : IReadDir + { + AuSPtr pDir; + AuList nextLevel; + AuList nextLevel2; + AuString curPath; + AuString curSubDir; + + bool OpenDir(const AuString &str) + { + curPath = str; + pDir = ReadDir(str); + return bool(pDir); + } + + bool OpenNext(const AuString &str) + { + curPath = str; + pDir = ReadDir(str); + return bool(pDir); + } + + void DoNext() + { + this->pDir.reset(); + + if (!nextLevel.size()) + { + return; + } + + auto a = nextLevel[0]; + nextLevel.erase(nextLevel.begin()); + this->pDir = ReadDir(curPath + "/" + a); + curSubDir = a; + } + + virtual StatEx *Next() override + { + if (!this->pDir) + { + return {}; + } + + auto pNext = this->pDir->Next(); + while (!pNext) + { + DoNext(); + + if (!this->pDir) + { + return {}; + } + + pNext = this->pDir->Next(); + } + + if (curSubDir.size()) + { + pNext->fileName.insert(pNext->fileName.begin(), curSubDir.begin(), curSubDir.end()); + } + + if (pNext->bExistsDirectory) + { + nextLevel.push_back(pNext->fileName + "/"); + nextLevel2.push_back(pNext->fileName + "/"); + } + else + { + AuFS::Remove(pNext->path); + } + + return pNext; + } + + void RemoveDirs() + { + for (auto itr = nextLevel2.rbegin(); itr != nextLevel2.rend(); itr++) + { + AuFS::Remove(curPath + "/" + itr->c_str()); + } + } + }; + + AUKN_SYM bool DirDeleter(const AuString &string) + { + auto pObj = AuMakeShared(); + if (!pObj) + { + SysPushErrorMem(); + return {}; + } + + if (!pObj->OpenDir(string)) + { + return {}; + } + + while (pObj->Next()) + { + + } + + pObj->RemoveDirs(); + + AuFS::Remove(string); + return !AuFS::DirExists(string); + } +} \ No newline at end of file diff --git a/Source/IO/FS/DirDeleter.hpp b/Source/IO/FS/DirDeleter.hpp new file mode 100644 index 00000000..764a146a --- /dev/null +++ b/Source/IO/FS/DirDeleter.hpp @@ -0,0 +1,13 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: DirDeleter.hpp + Date: 2022-11-06 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO::FS +{ + +} \ No newline at end of file diff --git a/Source/IO/FS/FSRecursion.cpp b/Source/IO/FS/FSRecursion.cpp new file mode 100644 index 00000000..aae692b3 --- /dev/null +++ b/Source/IO/FS/FSRecursion.cpp @@ -0,0 +1,98 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: FSRecursion.cpp + Date: 2022-11-06 + Author: Reece +***/ +#include +#include "FS.hpp" + +namespace Aurora::IO::FS +{ + struct RecursiveDirIterator : IReadDir + { + AuSPtr pDir; + AuList nextLevel; + AuString curPath; + AuString curSubDir; + + bool OpenDir(const AuString &str) + { + curPath = str; + pDir = ReadDir(str); + return bool(pDir); + } + + bool OpenNext(const AuString &str) + { + curPath = str; + pDir = ReadDir(str); + return bool(pDir); + } + + void DoNext() + { + this->pDir.reset(); + + if (!nextLevel.size()) + { + return; + } + + auto a = nextLevel[0]; + nextLevel.erase(nextLevel.begin()); + pDir = ReadDir(curPath + "/" + a); + curSubDir = a; + } + + virtual StatEx *Next() override + { + if (!this->pDir) + { + return {}; + } + + auto pNext = this->pDir->Next(); + while (!pNext) + { + DoNext(); + if (!this->pDir) + { + return {}; + } + + pNext = this->pDir->Next(); + } + + if (curSubDir.size()) + { + pNext->fileName.insert(pNext->fileName.begin(), curSubDir.begin(), curSubDir.end()); + } + + if (pNext->bExistsDirectory) + { + nextLevel.push_back(pNext->fileName + "/"); + } + + return pNext; + } + }; + + AUKN_SYM AuSPtr ReadDirRecursive(const AuString &string) + { + auto pObj = AuMakeShared(); + if (!pObj) + { + SysPushErrorMem(); + return {}; + } + + if (!pObj->OpenDir(string)) + { + return {}; + } + + return pObj; + } +} \ No newline at end of file diff --git a/Source/IO/FS/FSRecursion.hpp b/Source/IO/FS/FSRecursion.hpp new file mode 100644 index 00000000..962f501c --- /dev/null +++ b/Source/IO/FS/FSRecursion.hpp @@ -0,0 +1,13 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: FSRecursion.hpp + Date: 2022-11-06 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO::FS +{ + +} \ No newline at end of file diff --git a/Source/Threading/Primitives/RWLock.cpp b/Source/Threading/Primitives/RWLock.cpp index 3db5e4fd..47dce5b8 100644 --- a/Source/Threading/Primitives/RWLock.cpp +++ b/Source/Threading/Primitives/RWLock.cpp @@ -78,6 +78,7 @@ namespace Aurora::Threading::Primitives bool RWLockImpl::LockRead(AuUInt64 timeout) { + #if 0 AU_LOCK_GUARD(mutex_); if (this->state_ == -1 && this->reentrantWriteLockHandle_ == AuThreads::GetThreadId()) @@ -102,11 +103,53 @@ namespace Aurora::Threading::Primitives } this->state_++; + #else + + if (this->state_ == -1 && this->reentrantWriteLockHandle_ == AuThreads::GetThreadId()) + { + return true; + } + + AuInt32 iCurState {}; + do + { + iCurState = this->state_; + + if (iCurState < 0) + { + AU_LOCK_GUARD(this->mutex_); + + iCurState = this->state_; + if (iCurState < 0) + { + if (!this->condition_->WaitForSignal(timeout)) + { + return false; + } + + if (this->writersPending_) + { + this->condition_->Broadcast(); + continue; + } + + return true; + } + } + } + while (AuAtomicCompareExchange(&this->state_, iCurState + 1, iCurState) != iCurState); + + #endif return true; } bool RWLockImpl::LockWrite(AuUInt64 timeout) { + if (AuAtomicCompareExchange(&this->state_, -1, 0) == 0) + { + return true; + } + AU_LOCK_GUARD(this->mutex_); this->writersPending_++; @@ -127,14 +170,14 @@ namespace Aurora::Threading::Primitives bool RWLockImpl::TryLockRead() { - if (this->state_ == -1) + auto iCurState = this->state_; + + if (iCurState == -1) { return this->reentrantWriteLockHandle_ == AuThreads::GetThreadId(); } - AU_LOCK_GUARD(mutex_); - this->state_++; - return true; + return AuAtomicCompareExchange(&this->state_, iCurState + 1, iCurState) != iCurState; } bool RWLockImpl::TryLockWrite() @@ -227,23 +270,23 @@ namespace Aurora::Threading::Primitives AUKN_SYM IRWLock *RWLockNew() { - auto ret = _new RWLockImpl(); - if (!ret) + auto pRwLock = _new RWLockImpl(); + if (!pRwLock) { return nullptr; } - if (!ret->Init()) + if (!pRwLock->Init()) { - delete ret; + delete pRwLock; return nullptr; } - return ret; + return pRwLock; } - AUKN_SYM void RWLockRelease(IRWLock *waitable) + AUKN_SYM void RWLockRelease(IRWLock *pRwLock) { - AuSafeDelete(waitable); + AuSafeDelete(pRwLock); } } \ No newline at end of file