mirror of
https://onedev.site.tesses.net/tesses-framework
synced 2026-03-26 04:30:21 +00:00
Change version 0.0.1
This commit is contained in:
@@ -10,6 +10,13 @@
|
||||
#include <utime.h>
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
#include "TessesFramework/Threading/Thread.hpp"
|
||||
#if defined(__linux__)
|
||||
#include <poll.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
namespace Tesses::Framework::Filesystem
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
@@ -249,8 +256,184 @@ namespace Tesses::Framework::Filesystem
|
||||
std::error_code error;
|
||||
std::filesystem::remove(VFSPathToSystem(path),error);
|
||||
}
|
||||
#if defined(__linux__)
|
||||
|
||||
class INotifyWatcher : public FSWatcher {
|
||||
std::shared_ptr<Threading::Thread> thrd;
|
||||
static uint32_t to_linux_mask(FSWatcherEventType flags)
|
||||
{
|
||||
uint32_t lflags = 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Accessed) != 0) ? IN_ACCESS : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::AttributeChanged) != 0) ? IN_ATTRIB : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Writen) != 0) ? IN_CLOSE_WRITE : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Read) != 0) ? IN_CLOSE_NOWRITE : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Created) != 0) ? IN_CREATE : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Deleted) != 0) ? IN_DELETE : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::WatchEntryDeleted) != 0) ? IN_DELETE_SELF : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Modified) != 0) ? IN_MODIFY : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::WatchEntryMoved) != 0) ? IN_MOVE_SELF : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveOld) != 0) ? IN_MOVED_FROM : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveNew) != 0) ? IN_MOVED_TO : 0;
|
||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Opened) != 0) ? IN_OPEN : 0;
|
||||
|
||||
return lflags;
|
||||
}
|
||||
static FSWatcherEventType from_linux_mask(uint32_t lflags)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
flags |= ((lflags & IN_ACCESS) != 0) ? (uint32_t)FSWatcherEventType::Accessed : 0;
|
||||
flags |= ((lflags & IN_ATTRIB) != 0) ? (uint32_t)FSWatcherEventType::AttributeChanged : 0;
|
||||
flags |= ((lflags & IN_CLOSE_WRITE) != 0) ? (uint32_t)FSWatcherEventType::Writen : 0;
|
||||
flags |= ((lflags & IN_CLOSE_NOWRITE) != 0) ? (uint32_t)FSWatcherEventType::Read : 0;
|
||||
flags |= ((lflags & IN_CREATE) != 0) ? (uint32_t)FSWatcherEventType::Created : 0;
|
||||
flags |= ((lflags & IN_DELETE) != 0) ? (uint32_t)FSWatcherEventType::Deleted : 0;
|
||||
flags |= ((lflags & IN_DELETE_SELF) != 0) ? (uint32_t)FSWatcherEventType::WatchEntryDeleted : 0;
|
||||
flags |= ((lflags & IN_MODIFY) != 0) ? (uint32_t)FSWatcherEventType::Modified : 0;
|
||||
flags |= ((lflags & IN_MOVE_SELF) != 0) ? (uint32_t)FSWatcherEventType::WatchEntryMoved : 0;
|
||||
flags |= ((lflags & IN_MOVED_FROM) != 0) ? (uint32_t)FSWatcherEventType::MoveOld : 0;
|
||||
flags |= ((lflags & IN_MOVED_TO) != 0) ? (uint32_t)FSWatcherEventType::MoveNew : 0;
|
||||
flags |= ((lflags & IN_OPEN) != 0) ? (uint32_t)FSWatcherEventType::Opened : 0;
|
||||
|
||||
return (FSWatcherEventType)flags;
|
||||
}
|
||||
public:
|
||||
INotifyWatcher(std::shared_ptr<VFS> vfs, VFSPath path) : FSWatcher(vfs,path)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void SetEnabledImpl(bool enabled)
|
||||
{
|
||||
if(enabled)
|
||||
{
|
||||
int fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||
if (fd == -1)
|
||||
{
|
||||
throw std::runtime_error("Cannot init inotify");
|
||||
}
|
||||
auto str = this->GetFilesystem()->VFSPathToSystem(this->GetPath());
|
||||
|
||||
int watch = inotify_add_watch(fd, str.c_str(),to_linux_mask(this->events));
|
||||
|
||||
thrd = std::make_shared<Threading::Thread>([this,watch,fd]()-> void {
|
||||
int cnt = 0;
|
||||
struct pollfd pfd = {.fd = fd, .events = POLLIN};
|
||||
std::vector<std::pair<VFSPath,uint32_t>> mvFroms;
|
||||
char buf[4096]
|
||||
__attribute__ ((aligned(__alignof__(struct inotify_event))));
|
||||
const struct inotify_event *event;
|
||||
ssize_t size;
|
||||
|
||||
bool fail=false;
|
||||
|
||||
FSWatcherEvent evt;
|
||||
evt.dest = this->GetPath();
|
||||
while(!fail && this->enabled)
|
||||
{
|
||||
cnt = poll(&pfd,1,-1);
|
||||
if(cnt == -1) break;
|
||||
|
||||
if(cnt > 0)
|
||||
{
|
||||
if(pfd.revents & POLLIN)
|
||||
{
|
||||
for (;;) {
|
||||
size = read(fd, buf, sizeof(buf));
|
||||
if (size == -1 && errno != EAGAIN) {
|
||||
fail=true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (size <= 0)
|
||||
break;
|
||||
|
||||
for (char *ptr = buf; ptr < buf + size;
|
||||
ptr += sizeof(struct inotify_event) + event->len) {
|
||||
|
||||
event = (const struct inotify_event *) ptr;
|
||||
VFSPath path = this->GetPath();
|
||||
|
||||
if(event->len)
|
||||
path = path / std::string(event->name, (size_t)event->len);
|
||||
|
||||
if(((uint32_t)this->events & (uint32_t)FSWatcherEventType::Moved) == (uint32_t)FSWatcherEventType::Moved && event->mask & IN_MOVED_FROM)
|
||||
{
|
||||
mvFroms.emplace_back(path,event->cookie);
|
||||
}
|
||||
else if(((uint32_t)this->events & (uint32_t)FSWatcherEventType::Moved) == (uint32_t)FSWatcherEventType::Moved && event->mask & IN_MOVED_TO)
|
||||
{
|
||||
for(auto ittr = mvFroms.begin(); ittr != mvFroms.end(); ittr++)
|
||||
{
|
||||
if(ittr->second == event->cookie)
|
||||
{
|
||||
evt.src = ittr->first;
|
||||
mvFroms.erase(ittr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
evt.isDir = (event->mask & IN_ISDIR);
|
||||
evt.dest = path;
|
||||
evt.type = FSWatcherEventType::Moved;
|
||||
if(this->event)
|
||||
this->event(evt);
|
||||
}
|
||||
else {
|
||||
|
||||
evt.isDir = (event->mask & IN_ISDIR);
|
||||
evt.src = path;
|
||||
evt.type = from_linux_mask(event->mask);;
|
||||
if(this->event)
|
||||
this->event(evt);
|
||||
}
|
||||
if(event->mask & IN_MOVE_SELF)
|
||||
{
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
if(event->mask & IN_DELETE_SELF)
|
||||
{
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
thrd = nullptr;
|
||||
}
|
||||
}
|
||||
public:
|
||||
~INotifyWatcher()
|
||||
{
|
||||
this->enabled = false;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
std::shared_ptr<FSWatcher> LocalFilesystem::CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
return std::make_shared<INotifyWatcher>(vfs, path);
|
||||
#endif
|
||||
return VFS::CreateWatcher(vfs,path);
|
||||
}
|
||||
|
||||
std::shared_ptr<LocalFilesystem> LocalFS = std::make_shared<LocalFilesystem>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
// C:/Users/Jim/Joel
|
||||
|
||||
@@ -232,7 +232,8 @@ namespace Tesses::Framework::Filesystem
|
||||
|
||||
if(i == this->path.size()-1 && i == toMakeRelativeTo.path.size()-1)
|
||||
{
|
||||
VFSPath path({this->path[this->path.size()-1]});
|
||||
std::vector<std::string> paths{this->path[this->path.size()-1]};
|
||||
VFSPath path(paths);
|
||||
path.relative = true;
|
||||
return path;
|
||||
}
|
||||
@@ -387,7 +388,8 @@ namespace Tesses::Framework::Filesystem
|
||||
if(ext.empty()) return;
|
||||
if(ext[0] != '.')
|
||||
{
|
||||
str += '.' + ext;
|
||||
str += '.';
|
||||
str += ext;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -560,4 +562,113 @@ namespace Tesses::Framework::Filesystem
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::shared_ptr<FSWatcher> VFS::CreateWatcher(std::shared_ptr<VFS> vfs,VFSPath path)
|
||||
{
|
||||
return std::make_shared<FSWatcher>(vfs,path);
|
||||
}
|
||||
void FSWatcher::SetEnabled(bool enabled)
|
||||
{
|
||||
if(this->enabled == enabled) return;
|
||||
this->enabled = enabled;
|
||||
this->SetEnabledImpl(enabled);
|
||||
}
|
||||
|
||||
bool FSWatcher::GetEnabled()
|
||||
{
|
||||
return this->enabled;
|
||||
}
|
||||
|
||||
void FSWatcher::SetEnabledImpl(bool enabled)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<VFS> FSWatcher::GetFilesystem()
|
||||
{
|
||||
return this->vfs;
|
||||
}
|
||||
const VFSPath& FSWatcher::GetPath()
|
||||
{
|
||||
return this->path;
|
||||
}
|
||||
|
||||
FSWatcher::FSWatcher(std::shared_ptr<VFS> vfs, VFSPath path): vfs(vfs), path(path)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<FSWatcher> FSWatcher::Create(std::shared_ptr<VFS> vfs, VFSPath path)
|
||||
{
|
||||
return vfs->CreateWatcher(vfs,path);
|
||||
}
|
||||
|
||||
bool FSWatcherEvent::IsEvent(FSWatcherEventType e)
|
||||
{
|
||||
if(e == FSWatcherEventType::All) return this->type != FSWatcherEventType::None;
|
||||
if(e == FSWatcherEventType::Moved) return ((uint32_t)this->type & (uint32_t)FSWatcherEventType::Moved) == (uint32_t)FSWatcherEventType::Moved;
|
||||
if(e == FSWatcherEventType::Closed) return ((uint32_t)this->type & (uint32_t)FSWatcherEventType::Closed) != 0;
|
||||
return (uint32_t)this->type & (uint32_t)e;
|
||||
}
|
||||
|
||||
std::string FSWatcherEvent::ToString()
|
||||
{
|
||||
if(IsEvent(FSWatcherEventType::Moved))
|
||||
{
|
||||
return (this->isDir ? "Moved directory " : "Moved file ") + this->src.ToString() + " -> " + this->dest.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::MoveOld))
|
||||
{
|
||||
return (this->isDir ? "Move source directory " : "Move source file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::MoveNew))
|
||||
{
|
||||
return (this->isDir ? "Move destination directory " : "Move destination file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::Accessed))
|
||||
{
|
||||
return (this->isDir ? "Accessed directory " : "Accessed file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::AttributeChanged))
|
||||
{
|
||||
return (this->isDir ? "Changed attr on directory " : "Changed attr on file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::Writen))
|
||||
{
|
||||
return (this->isDir ? "Finished changing directory " : "Finished writing to file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::Read))
|
||||
{
|
||||
return (this->isDir ? "Finished reading directory " : "Finished reading from file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::Created))
|
||||
{
|
||||
return (this->isDir ? "Created directory " : "Created file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::Deleted))
|
||||
{
|
||||
return (this->isDir ? "Deleted directory " : "Deleted file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::WatchEntryDeleted))
|
||||
{
|
||||
|
||||
return (this->isDir ? "Deleted watched directory " : "Deleted watched file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::Modified))
|
||||
{
|
||||
return (this->isDir ? "Modified directory " : "Modified file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::WatchEntryMoved))
|
||||
{
|
||||
return (this->isDir ? "Moved watched directory " : "Moved watched file ") + this->src.ToString();
|
||||
}
|
||||
else if(IsEvent(FSWatcherEventType::Opened))
|
||||
{
|
||||
return (this->isDir ? "Opened directory " : "Opened file ") + this->src.ToString();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user