197 lines
6.1 KiB
C++
197 lines
6.1 KiB
C++
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
|
#include "TessesFramework/Streams/FileStream.hpp"
|
|
#include <iostream>
|
|
#include <sys/stat.h>
|
|
#if defined(_WIN32)
|
|
#include <windows.h>
|
|
#include "TessesFramework/Filesystem/VFSFix.hpp"
|
|
#undef min
|
|
#else
|
|
#include <utime.h>
|
|
#endif
|
|
namespace Tesses::Framework::Filesystem
|
|
{
|
|
#if defined(_WIN32)
|
|
static void TimetToFileTime(time_t t, LPFILETIME pft) {
|
|
ULARGE_INTEGER time_value;
|
|
time_value.QuadPart = (t * 10000000LL) + 116444736000000000LL;
|
|
pft->dwLowDateTime = time_value.LowPart;
|
|
pft->dwHighDateTime = time_value.HighPart;
|
|
}
|
|
#endif
|
|
void LocalFilesystem::GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess)
|
|
{
|
|
std::string s = VFSPathToSystem(path);
|
|
struct stat st;
|
|
if(stat(s.c_str(),&st) == 0)
|
|
{
|
|
lastAccess = st.st_atime;
|
|
lastWrite = st.st_mtime;
|
|
}
|
|
}
|
|
void LocalFilesystem::SetDate(VFSPath path, time_t lastWrite, time_t lastAccess)
|
|
{
|
|
std::string s = VFSPathToSystem(path);
|
|
#if defined(TESSESFRAMEWORK_ENABLE_SETDATE)
|
|
#if defined(_WIN32)
|
|
FILETIME lastWriteF;
|
|
FILETIME lastAccessF;
|
|
TimetToFileTime(lastWrite,&lastWriteF);
|
|
TimetToFileTime(lastAccess,&lastAccessF);
|
|
HANDLE hFile = CreateFileA(
|
|
s.c_str(),
|
|
FILE_WRITE_ATTRIBUTES,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_BACKUP_SEMANTICS, // For directories
|
|
NULL
|
|
);
|
|
if(hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
SetFileTime(
|
|
hFile,
|
|
NULL,
|
|
&lastAccessF,
|
|
&lastWriteF
|
|
);
|
|
CloseHandle(hFile);
|
|
}
|
|
#else
|
|
struct utimbuf utim;
|
|
utim.actime = lastAccess;
|
|
utim.modtime = lastWrite;
|
|
utime(s.c_str(),&utim);
|
|
#endif
|
|
#endif
|
|
}
|
|
VFSPath LocalFilesystem::ReadLink(VFSPath path)
|
|
{
|
|
auto res = std::filesystem::read_symlink(this->VFSPathToSystem(path)).string();
|
|
return this->SystemToVFSPath(res.c_str());
|
|
}
|
|
Tesses::Framework::Streams::Stream* LocalFilesystem::OpenFile(VFSPath path, std::string mode)
|
|
{
|
|
return new Tesses::Framework::Streams::FileStream(VFSPathToSystem(path), mode);
|
|
}
|
|
|
|
void LocalFilesystem::DeleteDirectory(VFSPath path)
|
|
{
|
|
std::filesystem::remove(VFSPathToSystem(path));
|
|
}
|
|
void LocalFilesystem::DeleteFile(VFSPath path)
|
|
{
|
|
std::filesystem::remove(VFSPathToSystem(path));
|
|
}
|
|
void LocalFilesystem::CreateDirectory(VFSPath path)
|
|
{
|
|
std::filesystem::create_directories(VFSPathToSystem(path));
|
|
}
|
|
bool LocalFilesystem::DirectoryExists(VFSPath path)
|
|
{
|
|
return std::filesystem::is_directory(VFSPathToSystem(path));
|
|
}
|
|
bool LocalFilesystem::RegularFileExists(VFSPath path)
|
|
{
|
|
return std::filesystem::is_regular_file(VFSPathToSystem(path));
|
|
}
|
|
bool LocalFilesystem::SymlinkExists(VFSPath path)
|
|
{
|
|
return std::filesystem::is_symlink(VFSPathToSystem(path));
|
|
}
|
|
bool LocalFilesystem::BlockDeviceExists(VFSPath path)
|
|
{
|
|
return std::filesystem::is_block_file(VFSPathToSystem(path));
|
|
}
|
|
bool LocalFilesystem::CharacterDeviceExists(VFSPath path)
|
|
{
|
|
return std::filesystem::is_character_file(VFSPathToSystem(path));
|
|
}
|
|
bool LocalFilesystem::SocketFileExists(VFSPath path)
|
|
{
|
|
return std::filesystem::is_socket(VFSPathToSystem(path));
|
|
}
|
|
bool LocalFilesystem::FIFOFileExists(VFSPath path)
|
|
{
|
|
return std::filesystem::is_fifo(VFSPathToSystem(path));
|
|
}
|
|
void LocalFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
|
|
{
|
|
if(std::filesystem::is_directory(VFSPathToSystem(existingFile)))
|
|
{
|
|
std::filesystem::create_directory_symlink(VFSPathToSystem(existingFile),VFSPathToSystem(symlinkFile));
|
|
}
|
|
else
|
|
{
|
|
std::filesystem::create_symlink(VFSPathToSystem(existingFile),VFSPathToSystem(symlinkFile));
|
|
}
|
|
}
|
|
void LocalFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName)
|
|
{
|
|
std::filesystem::create_hard_link(VFSPathToSystem(existingFile),VFSPathToSystem(newName));
|
|
}
|
|
void LocalFilesystem::MoveFile(VFSPath src, VFSPath dest)
|
|
{
|
|
std::filesystem::rename(VFSPathToSystem(src),VFSPathToSystem(dest));
|
|
}
|
|
void LocalFilesystem::MoveDirectory(VFSPath src, VFSPath dest)
|
|
{
|
|
std::filesystem::rename(VFSPathToSystem(src),VFSPathToSystem(dest));
|
|
}
|
|
std::string LocalFilesystem::VFSPathToSystem(VFSPath path)
|
|
{
|
|
#if defined(_WIN32)
|
|
bool first=true;
|
|
std::string p = {};
|
|
for(auto item : path.path)
|
|
{
|
|
if(!(first && !item.empty() && item.back()==':') && !(first && path.relative))
|
|
p.push_back('\\');
|
|
p.append(item);
|
|
first=false;
|
|
}
|
|
return p;
|
|
|
|
#else
|
|
return path.ToString();
|
|
#endif
|
|
}
|
|
VFSPath LocalFilesystem::SystemToVFSPath(std::string path)
|
|
{
|
|
VFSPath p;
|
|
p.path = VFSPath::SplitPath(path);
|
|
p.relative=true;
|
|
if(!path.empty())
|
|
{
|
|
if(path.front() == '/') p.relative=false;
|
|
if(!p.path.empty())
|
|
{
|
|
auto firstPartPath = p.path.front();
|
|
|
|
if(!firstPartPath.empty() && firstPartPath.back() == '/') p.relative=false;
|
|
}
|
|
}
|
|
return p;
|
|
}
|
|
|
|
VFSPathEnumerator LocalFilesystem::EnumeratePaths(VFSPath path)
|
|
{
|
|
auto dir = new std::filesystem::directory_iterator(VFSPathToSystem(path));
|
|
return VFSPathEnumerator([dir,path](VFSPath& path0)->bool {
|
|
std::filesystem::directory_iterator& ittr = *dir;
|
|
if(ittr != std::filesystem::directory_iterator())
|
|
{
|
|
path0 = VFSPath(path, ittr->path().filename().string());
|
|
ittr++;
|
|
return true;
|
|
}
|
|
return false;
|
|
},[dir]()->void{
|
|
delete dir;
|
|
});
|
|
}
|
|
LocalFilesystem LocalFS;
|
|
}
|
|
|
|
// C:/Users/Jim/Joel
|