diff --git a/cmake/sources.cmake b/cmake/sources.cmake index fafa569..6588531 100644 --- a/cmake/sources.cmake +++ b/cmake/sources.cmake @@ -47,6 +47,7 @@ src/Filesystem/LocalFS.cpp src/Filesystem/SubdirFilesystem.cpp src/Filesystem/NullFilesystem.cpp src/Filesystem/MountableFilesystem.cpp +src/Filesystem/RelativeFilesystem.cpp src/Filesystem/FSHelpers.cpp src/Filesystem/TempFS.cpp src/Crypto/MbedTLS/ClientTLSStream.cpp diff --git a/include/TessesFramework/Filesystem/RelativeFilesystem.hpp b/include/TessesFramework/Filesystem/RelativeFilesystem.hpp new file mode 100644 index 0000000..c82c95e --- /dev/null +++ b/include/TessesFramework/Filesystem/RelativeFilesystem.hpp @@ -0,0 +1,54 @@ +#pragma once +#include "VFS.hpp" +#include "VFSFix.hpp" + +namespace Tesses::Framework::Filesystem +{ + class RelativeFilesystem : public VFS { + Tesses::Framework::Threading::Mutex mtx; + VFSPath working; + std::shared_ptr vfs; + private: + VFSPath ToParent(VFSPath path); + public: + RelativeFilesystem(std::shared_ptr vfs, VFSPath working); + VFSPath GetWorking(); + void SetWorking(VFSPath path); + std::shared_ptr GetVFS(); + + std::shared_ptr OpenFile(VFSPath path, std::string mode); + void CreateDirectory(VFSPath path); + void DeleteDirectory(VFSPath path); + void DeleteFile(VFSPath path); + void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); + VFSPathEnumerator EnumeratePaths(VFSPath path); + void CreateHardlink(VFSPath existingFile, VFSPath newName); + void MoveFile(VFSPath src, VFSPath dest); + void MoveDirectory(VFSPath src, VFSPath dest); + void DeleteDirectoryRecurse(VFSPath path); + VFSPath ReadLink(VFSPath path); + std::string VFSPathToSystem(VFSPath path); + VFSPath SystemToVFSPath(std::string path); + void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); + bool StatVFS(VFSPath path, StatVFSData& vfsData); + bool Stat(VFSPath path, StatData& data); + + void Chown(VFSPath path, uint32_t uid, uint32_t gid); + void Chmod(VFSPath path, uint32_t mode); + FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode); + void Lock(VFSPath path); + void Unlock(VFSPath path); + protected: + std::shared_ptr CreateWatcher(std::shared_ptr vfs, VFSPath path); + + + class Watcher : public FSWatcher { + std::shared_ptr watcher; + protected: + void SetEnabledImpl(bool enabled); + public: + Watcher(std::shared_ptr vfs, VFSPath path); + ~Watcher(); + }; + }; +} \ No newline at end of file diff --git a/include/TessesFramework/Filesystem/SubdirFilesystem.hpp b/include/TessesFramework/Filesystem/SubdirFilesystem.hpp index bbf6db0..d0e341a 100644 --- a/include/TessesFramework/Filesystem/SubdirFilesystem.hpp +++ b/include/TessesFramework/Filesystem/SubdirFilesystem.hpp @@ -35,5 +35,19 @@ namespace Tesses::Framework::Filesystem FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode); void Lock(VFSPath path); void Unlock(VFSPath path); + + + protected: + std::shared_ptr CreateWatcher(std::shared_ptr vfs, VFSPath path); + + + class Watcher : public FSWatcher { + std::shared_ptr watcher; + protected: + void SetEnabledImpl(bool enabled); + public: + Watcher(std::shared_ptr vfs, VFSPath path); + ~Watcher(); + }; }; } diff --git a/include/TessesFramework/Filesystem/TempFS.hpp b/include/TessesFramework/Filesystem/TempFS.hpp index 3bd8c5e..4676446 100644 --- a/include/TessesFramework/Filesystem/TempFS.hpp +++ b/include/TessesFramework/Filesystem/TempFS.hpp @@ -44,5 +44,9 @@ namespace Tesses::Framework::Filesystem void Lock(VFSPath path); void Unlock(VFSPath path); ~TempFS(); + + protected: + std::shared_ptr CreateWatcher(std::shared_ptr vfs, VFSPath path); + }; } diff --git a/include/TessesFramework/TessesFramework.hpp b/include/TessesFramework/TessesFramework.hpp index 667c2fd..f359ec3 100644 --- a/include/TessesFramework/TessesFramework.hpp +++ b/include/TessesFramework/TessesFramework.hpp @@ -31,6 +31,7 @@ #include "Filesystem/SubdirFilesystem.hpp" #include "Filesystem/NullFilesystem.hpp" #include "Filesystem/MountableFilesystem.hpp" +#include "Filesystem/RelativeFilesystem.hpp" #include "Filesystem/FSHelpers.hpp" #include "Crypto/ClientTLSStream.hpp" #include "Crypto/Crypto.hpp" diff --git a/src/Filesystem/RelativeFilesystem.cpp b/src/Filesystem/RelativeFilesystem.cpp new file mode 100644 index 0000000..b09d4a2 --- /dev/null +++ b/src/Filesystem/RelativeFilesystem.cpp @@ -0,0 +1,206 @@ +#include "TessesFramework/Filesystem/RelativeFilesystem.hpp" + +namespace Tesses::Framework::Filesystem +{ + VFSPath RelativeFilesystem::ToParent(VFSPath path) + { + if(path.relative) + { + return path.MakeAbsolute(GetWorking()); + } + else + { + return path; + } + } + + RelativeFilesystem::RelativeFilesystem(std::shared_ptr vfs, VFSPath working) : vfs(vfs), working(working) + { + + } + VFSPath RelativeFilesystem::GetWorking() + { + mtx.Lock(); + auto p = this->working; + mtx.Unlock(); + return p; + } + void RelativeFilesystem::SetWorking(VFSPath path) + { + mtx.Lock(); + this->working=path; + mtx.Unlock(); + } + std::shared_ptr RelativeFilesystem::GetVFS() + { + return vfs; + } + + std::shared_ptr RelativeFilesystem::OpenFile(VFSPath path, std::string mode) + { + return this->vfs->OpenFile(ToParent(path),mode); + } + void RelativeFilesystem::CreateDirectory(VFSPath path) + { + this->vfs->CreateDirectory(ToParent(path)); + } + void RelativeFilesystem::DeleteDirectory(VFSPath path) + { + this->vfs->DeleteDirectory(ToParent(path)); + } + void RelativeFilesystem::DeleteFile(VFSPath path) + { + this->vfs->DeleteFile(ToParent(path)); + } + void RelativeFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile) + { + this->vfs->CreateSymlink(existingFile, ToParent(symlinkFile)); + } + VFSPathEnumerator RelativeFilesystem::EnumeratePaths(VFSPath path) + { + VFSPathEnumerator* enumerator = this->vfs->EnumeratePaths(ToParent(path)).MakePointer(); + + return VFSPathEnumerator([enumerator,path,this](VFSPath& path0)->bool{ + if(enumerator->MoveNext()) + { + path0 = path / enumerator->Current.GetFileName(); + return true; + } + return false; + },[enumerator]()->void{ + delete enumerator; + }); + } + void RelativeFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName) + { + if(existingFile.relative || newName.relative) + { + auto working = GetWorking(); + if(existingFile.relative) + existingFile = existingFile.MakeAbsolute(working); + + if(newName.relative) + newName = newName.MakeAbsolute(working); + } + vfs->CreateHardlink(existingFile, newName); + } + void RelativeFilesystem::MoveFile(VFSPath src, VFSPath dest) + { + if(src.relative || dest.relative) + { + auto working = GetWorking(); + if(src.relative) + src = src.MakeAbsolute(working); + + if(dest.relative) + dest = dest.MakeAbsolute(working); + } + vfs->MoveFile(src, dest); + } + void RelativeFilesystem::MoveDirectory(VFSPath src, VFSPath dest) + { + if(src.relative || dest.relative) + { + auto working = GetWorking(); + if(src.relative) + src = src.MakeAbsolute(working); + + if(dest.relative) + dest = dest.MakeAbsolute(working); + } + vfs->MoveDirectory(src, dest); + } + void RelativeFilesystem::DeleteDirectoryRecurse(VFSPath path) + { + vfs->DeleteDirectoryRecurse(ToParent(path)); + } + VFSPath RelativeFilesystem::ReadLink(VFSPath path) + { + return vfs->ReadLink(ToParent(path)); + } + std::string RelativeFilesystem::VFSPathToSystem(VFSPath path) + { + return vfs->VFSPathToSystem(path); + } + VFSPath RelativeFilesystem::SystemToVFSPath(std::string path) + { + return vfs->SystemToVFSPath(path); + } + void RelativeFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) + { + vfs->SetDate(ToParent(path),lastWrite,lastAccess); + } + bool RelativeFilesystem::StatVFS(VFSPath path, StatVFSData& vfsData) + { + return vfs->StatVFS(ToParent(path), vfsData); + } + bool RelativeFilesystem::Stat(VFSPath path, StatData& data) + { + return vfs->Stat(ToParent(path),data); + } + + void RelativeFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid) + { + vfs->Chown(ToParent(path),uid,gid); + } + void RelativeFilesystem::Chmod(VFSPath path, uint32_t mode) + { + vfs->Chmod(ToParent(path), mode); + } + FIFOCreationResult RelativeFilesystem::CreateFIFO(VFSPath path, uint32_t mode) + { + return vfs->CreateFIFO(ToParent(path),mode); + } + void RelativeFilesystem::Lock(VFSPath path) + { + vfs->Lock(ToParent(path)); + } + void RelativeFilesystem::Unlock(VFSPath path) + { + vfs->Unlock(ToParent(path)); + } + + + RelativeFilesystem::Watcher::Watcher(std::shared_ptr vfs, VFSPath path) : FSWatcher(vfs, path) + { + this->watcher = FSWatcher::Create(vfs->vfs, vfs->ToParent(path)); + this->watcher->event = [vfs,this,path](FSWatcherEvent & evt)-> void{ + if(path.relative) + { + auto working = vfs->GetWorking(); + FSWatcherEvent e2=evt; + if(evt.IsEvent(FSWatcherEventType::Moved)) + { + e2.dest = e2.dest.MakeRelative(working); + } + e2.src = e2.src.MakeRelative(working); + + if(this->event) this->event(e2); + } + else { + if(this->event) + this->event(evt); + } + }; + } + + void RelativeFilesystem::Watcher::SetEnabledImpl(bool enabled) + { + this->enabled = enabled; + this->watcher->events = this->events; + this->watcher->SetEnabled(enabled); + } + RelativeFilesystem::Watcher::~Watcher() + { + this->watcher->SetEnabled(false); + } + std::shared_ptr RelativeFilesystem::CreateWatcher(std::shared_ptr vfs, VFSPath path) + { + auto sdfs = std::dynamic_pointer_cast(vfs); + if(sdfs) + { + return std::make_shared(sdfs,path); + } + return VFS::CreateWatcher(vfs,path); + } +} \ No newline at end of file diff --git a/src/Filesystem/SubdirFilesystem.cpp b/src/Filesystem/SubdirFilesystem.cpp index 39af1f2..e0f3d4f 100644 --- a/src/Filesystem/SubdirFilesystem.cpp +++ b/src/Filesystem/SubdirFilesystem.cpp @@ -77,7 +77,7 @@ namespace Tesses::Framework::Filesystem { VFSPathEnumerator* enumerator = this->parent->EnumeratePaths(ToParent(path)).MakePointer(); - return VFSPathEnumerator([enumerator,path,this](VFSPath& path0)->bool{ + return VFSPathEnumerator([enumerator,this](VFSPath& path0)->bool{ if(enumerator->MoveNext()) { path0 = FromParent(enumerator->Current); @@ -146,4 +146,40 @@ namespace Tesses::Framework::Filesystem { return this->parent->CreateFIFO(path, mod); } + + SubdirFilesystem::Watcher::Watcher(std::shared_ptr vfs, VFSPath path) : FSWatcher(vfs, path) + { + this->watcher = FSWatcher::Create(vfs->parent, vfs->ToParent(path)); + this->watcher->event = [vfs,this](FSWatcherEvent & evt)-> void{ + FSWatcherEvent e2=evt; + if(evt.IsEvent(FSWatcherEventType::Moved)) + { + e2.dest = vfs->FromParent(e2.dest); + } + e2.src = vfs->FromParent(e2.src); + + if(this->event) this->event(e2); + }; + } + + void SubdirFilesystem::Watcher::SetEnabledImpl(bool enabled) + { + this->enabled = enabled; + this->watcher->events = this->events; + this->watcher->SetEnabled(enabled); + } + SubdirFilesystem::Watcher::~Watcher() + { + this->watcher->SetEnabled(false); + } + std::shared_ptr SubdirFilesystem::CreateWatcher(std::shared_ptr vfs, VFSPath path) + { + auto sdfs = std::dynamic_pointer_cast(vfs); + if(sdfs) + { + return std::make_shared(sdfs,path); + } + return VFS::CreateWatcher(vfs,path); + } + } diff --git a/src/Filesystem/TempFS.cpp b/src/Filesystem/TempFS.cpp index d5ce8e2..96e5b58 100644 --- a/src/Filesystem/TempFS.cpp +++ b/src/Filesystem/TempFS.cpp @@ -170,6 +170,11 @@ namespace Tesses::Framework::Filesystem { if(this->deleteOnDestroy && this->parent->DirectoryExists(p)) this->parent->DeleteDirectoryRecurse(p); } + std::shared_ptr TempFS::CreateWatcher(std::shared_ptr vfs, VFSPath path) + { + return FSWatcher::Create(vfs,path); + } + TempFS::~TempFS() { VFSPath p;