630 lines
21 KiB
C++
630 lines
21 KiB
C++
|
#include "scriptfilesystem.h"
|
||
|
#include "../autowrapper/aswrappedcall.h"
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
#include <direct.h> // _getcwd
|
||
|
#include <Windows.h> // FindFirstFile, GetFileAttributes
|
||
|
|
||
|
#undef DeleteFile
|
||
|
#undef CopyFile
|
||
|
|
||
|
#else
|
||
|
#include <unistd.h> // getcwd
|
||
|
#include <dirent.h> // opendir, readdir, closedir
|
||
|
#include <sys/stat.h> // stat
|
||
|
#endif
|
||
|
#include <assert.h> // assert
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
BEGIN_AS_NAMESPACE
|
||
|
|
||
|
// TODO: The file system should have a way to allow the application to define in
|
||
|
// which sub directories it is allowed to make changes and/or read
|
||
|
|
||
|
CScriptFileSystem *ScriptFileSystem_Factory()
|
||
|
{
|
||
|
return new CScriptFileSystem();
|
||
|
}
|
||
|
|
||
|
void RegisterScriptFileSystem_Native(asIScriptEngine *engine)
|
||
|
{
|
||
|
int r;
|
||
|
|
||
|
assert( engine->GetTypeInfoByName("string") );
|
||
|
assert( engine->GetTypeInfoByDecl("array<string>") );
|
||
|
assert( engine->GetTypeInfoByName("datetime") );
|
||
|
|
||
|
r = engine->RegisterObjectType("filesystem", 0, asOBJ_REF); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_FACTORY, "filesystem @f()", asFUNCTION(ScriptFileSystem_Factory), asCALL_CDECL); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptFileSystem,AddRef), asCALL_THISCALL); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptFileSystem,Release), asCALL_THISCALL); assert( r >= 0 );
|
||
|
|
||
|
r = engine->RegisterObjectMethod("filesystem", "bool changeCurrentPath(const string &in)", asMETHOD(CScriptFileSystem, ChangeCurrentPath), asCALL_THISCALL); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectMethod("filesystem", "string getCurrentPath() const", asMETHOD(CScriptFileSystem, GetCurrentPath), asCALL_THISCALL); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectMethod("filesystem", "array<string> @getDirs() const", asMETHOD(CScriptFileSystem, GetDirs), asCALL_THISCALL); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectMethod("filesystem", "array<string> @getFiles() const", asMETHOD(CScriptFileSystem, GetFiles), asCALL_THISCALL); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectMethod("filesystem", "bool isDir(const string &in) const", asMETHOD(CScriptFileSystem, IsDir), asCALL_THISCALL); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectMethod("filesystem", "bool isLink(const string &in) const", asMETHOD(CScriptFileSystem, IsLink), asCALL_THISCALL); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int64 getSize(const string &in) const", asMETHOD(CScriptFileSystem, GetSize), asCALL_THISCALL); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int makeDir(const string &in)", asMETHOD(CScriptFileSystem, MakeDir), asCALL_THISCALL); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int removeDir(const string &in)", asMETHOD(CScriptFileSystem, RemoveDir), asCALL_THISCALL); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int deleteFile(const string &in)", asMETHOD(CScriptFileSystem, DeleteFile), asCALL_THISCALL); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int copyFile(const string &in, const string &in)", asMETHOD(CScriptFileSystem, CopyFile), asCALL_THISCALL); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int move(const string &in, const string &in)", asMETHOD(CScriptFileSystem, Move), asCALL_THISCALL); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "datetime getCreateDateTime(const string &in) const", asMETHOD(CScriptFileSystem, GetCreateDateTime), asCALL_THISCALL); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "datetime getModifyDateTime(const string &in) const", asMETHOD(CScriptFileSystem, GetModifyDateTime), asCALL_THISCALL); assert(r >= 0);
|
||
|
}
|
||
|
|
||
|
void RegisterScriptFileSystem_Generic(asIScriptEngine *engine)
|
||
|
{
|
||
|
int r;
|
||
|
|
||
|
assert( engine->GetTypeInfoByName("string") );
|
||
|
assert( engine->GetTypeInfoByDecl("array<string>") );
|
||
|
assert( engine->GetTypeInfoByName("datetime") );
|
||
|
|
||
|
r = engine->RegisterObjectType("filesystem", 0, asOBJ_REF); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_FACTORY, "filesystem @f()", WRAP_FN(ScriptFileSystem_Factory), asCALL_GENERIC); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_ADDREF, "void f()", WRAP_MFN(CScriptFileSystem,AddRef), asCALL_GENERIC); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_RELEASE, "void f()", WRAP_MFN(CScriptFileSystem,Release), asCALL_GENERIC); assert( r >= 0 );
|
||
|
|
||
|
r = engine->RegisterObjectMethod("filesystem", "bool changeCurrentPath(const string &in)", WRAP_MFN(CScriptFileSystem, ChangeCurrentPath), asCALL_GENERIC); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectMethod("filesystem", "string getCurrentPath() const", WRAP_MFN(CScriptFileSystem, GetCurrentPath), asCALL_GENERIC); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectMethod("filesystem", "array<string> @getDirs() const", WRAP_MFN(CScriptFileSystem, GetDirs), asCALL_GENERIC); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectMethod("filesystem", "array<string> @getFiles() const", WRAP_MFN(CScriptFileSystem, GetFiles), asCALL_GENERIC); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectMethod("filesystem", "bool isDir(const string &in) const", WRAP_MFN(CScriptFileSystem, IsDir), asCALL_GENERIC); assert( r >= 0 );
|
||
|
r = engine->RegisterObjectMethod("filesystem", "bool isLink(const string &in) const", WRAP_MFN(CScriptFileSystem, IsLink), asCALL_GENERIC); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int64 getSize(const string &in) const", WRAP_MFN(CScriptFileSystem, GetSize), asCALL_GENERIC); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int makeDir(const string &in)", WRAP_MFN(CScriptFileSystem, MakeDir), asCALL_GENERIC); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int removeDir(const string &in)", WRAP_MFN(CScriptFileSystem, RemoveDir), asCALL_GENERIC); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int deleteFile(const string &in)", WRAP_MFN(CScriptFileSystem, DeleteFile), asCALL_GENERIC); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int copyFile(const string &in, const string &in)", WRAP_MFN(CScriptFileSystem, CopyFile), asCALL_GENERIC); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "int move(const string &in, const string &in)", WRAP_MFN(CScriptFileSystem, Move), asCALL_GENERIC); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "datetime getCreateDateTime(const string &in) const", WRAP_MFN(CScriptFileSystem, GetCreateDateTime), asCALL_GENERIC); assert(r >= 0);
|
||
|
r = engine->RegisterObjectMethod("filesystem", "datetime getModifyDateTime(const string &in) const", WRAP_MFN(CScriptFileSystem, GetModifyDateTime), asCALL_GENERIC); assert(r >= 0);
|
||
|
}
|
||
|
|
||
|
void RegisterScriptFileSystem(asIScriptEngine *engine)
|
||
|
{
|
||
|
if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
|
||
|
RegisterScriptFileSystem_Generic(engine);
|
||
|
else
|
||
|
RegisterScriptFileSystem_Native(engine);
|
||
|
}
|
||
|
|
||
|
CScriptFileSystem::CScriptFileSystem()
|
||
|
{
|
||
|
refCount = 1;
|
||
|
|
||
|
// Gets the application's current working directory as the starting point
|
||
|
// TODO: Replace backslash with slash to keep a unified naming convention
|
||
|
char buffer[1000];
|
||
|
#if defined(_WIN32)
|
||
|
currentPath = _getcwd(buffer, 1000);
|
||
|
#else
|
||
|
currentPath = getcwd(buffer, 1000);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
CScriptFileSystem::~CScriptFileSystem()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CScriptFileSystem::AddRef() const
|
||
|
{
|
||
|
asAtomicInc(refCount);
|
||
|
}
|
||
|
|
||
|
void CScriptFileSystem::Release() const
|
||
|
{
|
||
|
if( asAtomicDec(refCount) == 0 )
|
||
|
delete this;
|
||
|
}
|
||
|
|
||
|
CScriptArray *CScriptFileSystem::GetFiles() const
|
||
|
{
|
||
|
// Obtain a pointer to the engine
|
||
|
asIScriptContext *ctx = asGetActiveContext();
|
||
|
asIScriptEngine *engine = ctx->GetEngine();
|
||
|
|
||
|
// TODO: This should only be done once
|
||
|
// TODO: This assumes that CScriptArray was already registered
|
||
|
asITypeInfo *arrayType = engine->GetTypeInfoByDecl("array<string>");
|
||
|
|
||
|
// Create the array object
|
||
|
CScriptArray *array = CScriptArray::Create(arrayType);
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16[10000];
|
||
|
string searchPattern = currentPath + "/*";
|
||
|
MultiByteToWideChar(CP_UTF8, 0, searchPattern.c_str(), -1, bufUTF16, 10000);
|
||
|
|
||
|
WIN32_FIND_DATAW ffd;
|
||
|
HANDLE hFind = FindFirstFileW(bufUTF16, &ffd);
|
||
|
if( INVALID_HANDLE_VALUE == hFind )
|
||
|
return array;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Skip directories
|
||
|
if( (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
||
|
continue;
|
||
|
|
||
|
// Convert the file name back to UTF8
|
||
|
char bufUTF8[10000];
|
||
|
WideCharToMultiByte(CP_UTF8, 0, ffd.cFileName, -1, bufUTF8, 10000, 0, 0);
|
||
|
|
||
|
// Add the file to the array
|
||
|
array->Resize(array->GetSize()+1);
|
||
|
((string*)(array->At(array->GetSize()-1)))->assign(bufUTF8);
|
||
|
}
|
||
|
while( FindNextFileW(hFind, &ffd) != 0 );
|
||
|
|
||
|
FindClose(hFind);
|
||
|
#else
|
||
|
dirent *ent = 0;
|
||
|
DIR *dir = opendir(currentPath.c_str());
|
||
|
while( (ent = readdir(dir)) != NULL )
|
||
|
{
|
||
|
const string filename = ent->d_name;
|
||
|
|
||
|
// Skip . and ..
|
||
|
if( filename[0] == '.' )
|
||
|
continue;
|
||
|
|
||
|
// Skip sub directories
|
||
|
const string fullname = currentPath + "/" + filename;
|
||
|
struct stat st;
|
||
|
if( stat(fullname.c_str(), &st) == -1 )
|
||
|
continue;
|
||
|
if( (st.st_mode & S_IFDIR) != 0 )
|
||
|
continue;
|
||
|
|
||
|
// Add the file to the array
|
||
|
array->Resize(array->GetSize()+1);
|
||
|
((string*)(array->At(array->GetSize()-1)))->assign(filename);
|
||
|
}
|
||
|
closedir(dir);
|
||
|
#endif
|
||
|
|
||
|
return array;
|
||
|
}
|
||
|
|
||
|
CScriptArray *CScriptFileSystem::GetDirs() const
|
||
|
{
|
||
|
// Obtain a pointer to the engine
|
||
|
asIScriptContext *ctx = asGetActiveContext();
|
||
|
asIScriptEngine *engine = ctx->GetEngine();
|
||
|
|
||
|
// TODO: This should only be done once
|
||
|
// TODO: This assumes that CScriptArray was already registered
|
||
|
asITypeInfo *arrayType = engine->GetTypeInfoByDecl("array<string>");
|
||
|
|
||
|
// Create the array object
|
||
|
CScriptArray *array = CScriptArray::Create(arrayType);
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16[10000];
|
||
|
string searchPattern = currentPath + "/*";
|
||
|
MultiByteToWideChar(CP_UTF8, 0, searchPattern.c_str(), -1, bufUTF16, 10000);
|
||
|
|
||
|
WIN32_FIND_DATAW ffd;
|
||
|
HANDLE hFind = FindFirstFileW(bufUTF16, &ffd);
|
||
|
if( INVALID_HANDLE_VALUE == hFind )
|
||
|
return array;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Skip files
|
||
|
if( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
||
|
continue;
|
||
|
|
||
|
// Convert the file name back to UTF8
|
||
|
char bufUTF8[10000];
|
||
|
WideCharToMultiByte(CP_UTF8, 0, ffd.cFileName, -1, bufUTF8, 10000, 0, 0);
|
||
|
|
||
|
if( strcmp(bufUTF8, ".") == 0 || strcmp(bufUTF8, "..") == 0 )
|
||
|
continue;
|
||
|
|
||
|
// Add the dir to the array
|
||
|
array->Resize(array->GetSize()+1);
|
||
|
((string*)(array->At(array->GetSize()-1)))->assign(bufUTF8);
|
||
|
}
|
||
|
while( FindNextFileW(hFind, &ffd) != 0 );
|
||
|
|
||
|
FindClose(hFind);
|
||
|
#else
|
||
|
dirent *ent = 0;
|
||
|
DIR *dir = opendir(currentPath.c_str());
|
||
|
while( (ent = readdir(dir)) != NULL )
|
||
|
{
|
||
|
const string filename = ent->d_name;
|
||
|
|
||
|
// Skip . and ..
|
||
|
if( filename[0] == '.' )
|
||
|
continue;
|
||
|
|
||
|
// Skip files
|
||
|
const string fullname = currentPath + "/" + filename;
|
||
|
struct stat st;
|
||
|
if( stat(fullname.c_str(), &st) == -1 )
|
||
|
continue;
|
||
|
if( (st.st_mode & S_IFDIR) == 0 )
|
||
|
continue;
|
||
|
|
||
|
// Add the dir to the array
|
||
|
array->Resize(array->GetSize()+1);
|
||
|
((string*)(array->At(array->GetSize()-1)))->assign(filename);
|
||
|
}
|
||
|
closedir(dir);
|
||
|
#endif
|
||
|
|
||
|
return array;
|
||
|
}
|
||
|
|
||
|
// Doesn't change anything if the new path is not valid
|
||
|
bool CScriptFileSystem::ChangeCurrentPath(const string &path)
|
||
|
{
|
||
|
string newPath;
|
||
|
if( path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0 )
|
||
|
newPath = path;
|
||
|
else
|
||
|
newPath = currentPath + "/" + path;
|
||
|
|
||
|
// TODO: Resolve internal /./ and /../
|
||
|
// TODO: Replace backslash with slash to keep a unified naming convention
|
||
|
|
||
|
// Remove trailing slashes from the path
|
||
|
while(newPath.length() && (newPath[newPath.length()-1] == '/' || newPath[newPath.length()-1] == '\\') )
|
||
|
newPath.resize(newPath.length()-1);
|
||
|
|
||
|
if (!IsDir(newPath))
|
||
|
return false;
|
||
|
|
||
|
currentPath = newPath;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CScriptFileSystem::IsDir(const string &path) const
|
||
|
{
|
||
|
string search;
|
||
|
if( path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0 )
|
||
|
search = path;
|
||
|
else
|
||
|
search = currentPath + "/" + path;
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||
|
|
||
|
// Check if the path exists and is a directory
|
||
|
DWORD attrib = GetFileAttributesW(bufUTF16);
|
||
|
if( attrib == INVALID_FILE_ATTRIBUTES ||
|
||
|
!(attrib & FILE_ATTRIBUTE_DIRECTORY) )
|
||
|
return false;
|
||
|
#else
|
||
|
// Check if the path exists and is a directory
|
||
|
struct stat st;
|
||
|
if( stat(search.c_str(), &st) == -1 )
|
||
|
return false;
|
||
|
if( (st.st_mode & S_IFDIR) == 0 )
|
||
|
return false;
|
||
|
#endif
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CScriptFileSystem::IsLink(const string &path) const
|
||
|
{
|
||
|
string search;
|
||
|
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||
|
search = path;
|
||
|
else
|
||
|
search = currentPath + "/" + path;
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||
|
|
||
|
// Check if the path exists and is a link
|
||
|
DWORD attrib = GetFileAttributesW(bufUTF16);
|
||
|
if (attrib == INVALID_FILE_ATTRIBUTES ||
|
||
|
!(attrib & FILE_ATTRIBUTE_REPARSE_POINT))
|
||
|
return false;
|
||
|
#else
|
||
|
// Check if the path exists and is a link
|
||
|
struct stat st;
|
||
|
if (stat(search.c_str(), &st) == -1)
|
||
|
return false;
|
||
|
if ((st.st_mode & S_IFLNK) == 0)
|
||
|
return false;
|
||
|
#endif
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
asINT64 CScriptFileSystem::GetSize(const string &path) const
|
||
|
{
|
||
|
string search;
|
||
|
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||
|
search = path;
|
||
|
else
|
||
|
search = currentPath + "/" + path;
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||
|
|
||
|
// Get the size of the file
|
||
|
LARGE_INTEGER largeInt;
|
||
|
HANDLE file = CreateFileW(bufUTF16, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||
|
BOOL success = GetFileSizeEx(file, &largeInt);
|
||
|
CloseHandle(file);
|
||
|
if( !success )
|
||
|
return -1;
|
||
|
return asINT64(largeInt.QuadPart);
|
||
|
#else
|
||
|
// Get the size of the file
|
||
|
struct stat st;
|
||
|
if (stat(search.c_str(), &st) == -1)
|
||
|
return -1;
|
||
|
return asINT64(st.st_size);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// TODO: Should be able to return different codes for
|
||
|
// - directory exists
|
||
|
// - path not found
|
||
|
// - access denied
|
||
|
// TODO: Should be able to define the permissions for the directory
|
||
|
int CScriptFileSystem::MakeDir(const string &path)
|
||
|
{
|
||
|
string search;
|
||
|
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||
|
search = path;
|
||
|
else
|
||
|
search = currentPath + "/" + path;
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||
|
|
||
|
// Create the directory
|
||
|
BOOL success = CreateDirectoryW(bufUTF16, 0);
|
||
|
return success ? 0 : -1;
|
||
|
#else
|
||
|
// Create the directory
|
||
|
int failure = mkdir(search.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||
|
return !failure ? 0 : -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// TODO: Should be able to return different codes for
|
||
|
// - directory doesn't exist
|
||
|
// - directory is not empty
|
||
|
// - access denied
|
||
|
// TODO: Should have an option to remove the directory and all content recursively
|
||
|
int CScriptFileSystem::RemoveDir(const string &path)
|
||
|
{
|
||
|
string search;
|
||
|
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||
|
search = path;
|
||
|
else
|
||
|
search = currentPath + "/" + path;
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||
|
|
||
|
// Remove the directory
|
||
|
BOOL success = RemoveDirectoryW(bufUTF16);
|
||
|
return success ? 0 : -1;
|
||
|
#else
|
||
|
// Remove the directory
|
||
|
int failure = rmdir(search.c_str());
|
||
|
return !failure ? 0 : -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int CScriptFileSystem::DeleteFile(const string &path)
|
||
|
{
|
||
|
string search;
|
||
|
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||
|
search = path;
|
||
|
else
|
||
|
search = currentPath + "/" + path;
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||
|
|
||
|
// Remove the file
|
||
|
BOOL success = DeleteFileW(bufUTF16);
|
||
|
return success ? 0 : -1;
|
||
|
#else
|
||
|
// Remove the file
|
||
|
int failure = unlink(search.c_str());
|
||
|
return !failure ? 0 : -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int CScriptFileSystem::CopyFile(const string &source, const string &target)
|
||
|
{
|
||
|
string search1;
|
||
|
if (source.find(":") != string::npos || source.find("/") == 0 || source.find("\\") == 0)
|
||
|
search1 = source;
|
||
|
else
|
||
|
search1 = currentPath + "/" + source;
|
||
|
|
||
|
string search2;
|
||
|
if (target.find(":") != string::npos || target.find("/") == 0 || target.find("\\") == 0)
|
||
|
search2 = target;
|
||
|
else
|
||
|
search2 = currentPath + "/" + target;
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16_1[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search1.c_str(), -1, bufUTF16_1, 10000);
|
||
|
|
||
|
wchar_t bufUTF16_2[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search2.c_str(), -1, bufUTF16_2, 10000);
|
||
|
|
||
|
// Copy the file
|
||
|
BOOL success = CopyFileW(bufUTF16_1, bufUTF16_2, TRUE);
|
||
|
return success ? 0 : -1;
|
||
|
#else
|
||
|
// Copy the file manually as there is no posix function for this
|
||
|
bool failure = false;
|
||
|
FILE *src = 0, *tgt = 0;
|
||
|
src = fopen(search1.c_str(), "r");
|
||
|
if (src == 0) failure = true;
|
||
|
if( !failure ) tgt = fopen(search2.c_str(), "w");
|
||
|
if (tgt == 0) failure = true;
|
||
|
char buf[1024];
|
||
|
size_t n;
|
||
|
while (!failure && (n = fread(buf, sizeof(char), sizeof(buf), src)) > 0)
|
||
|
{
|
||
|
if (fwrite(buf, sizeof(char), n, tgt) != n)
|
||
|
failure = true;
|
||
|
}
|
||
|
if (src) fclose(src);
|
||
|
if (tgt) fclose(tgt);
|
||
|
return !failure ? 0 : -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int CScriptFileSystem::Move(const string &source, const string &target)
|
||
|
{
|
||
|
string search1;
|
||
|
if (source.find(":") != string::npos || source.find("/") == 0 || source.find("\\") == 0)
|
||
|
search1 = source;
|
||
|
else
|
||
|
search1 = currentPath + "/" + source;
|
||
|
|
||
|
string search2;
|
||
|
if (target.find(":") != string::npos || target.find("/") == 0 || target.find("\\") == 0)
|
||
|
search2 = target;
|
||
|
else
|
||
|
search2 = currentPath + "/" + target;
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16_1[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search1.c_str(), -1, bufUTF16_1, 10000);
|
||
|
|
||
|
wchar_t bufUTF16_2[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search2.c_str(), -1, bufUTF16_2, 10000);
|
||
|
|
||
|
// Move the file or directory
|
||
|
BOOL success = MoveFileW(bufUTF16_1, bufUTF16_2);
|
||
|
return success ? 0 : -1;
|
||
|
#else
|
||
|
// Move the file or directory
|
||
|
int failure = rename(search1.c_str(), search2.c_str());
|
||
|
return !failure ? 0 : -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
string CScriptFileSystem::GetCurrentPath() const
|
||
|
{
|
||
|
return currentPath;
|
||
|
}
|
||
|
|
||
|
CDateTime CScriptFileSystem::GetCreateDateTime(const string &path) const
|
||
|
{
|
||
|
string search;
|
||
|
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||
|
search = path;
|
||
|
else
|
||
|
search = currentPath + "/" + path;
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||
|
|
||
|
// Get the create date/time of the file
|
||
|
FILETIME createTm;
|
||
|
HANDLE file = CreateFileW(bufUTF16, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||
|
BOOL success = GetFileTime(file, &createTm, 0, 0);
|
||
|
CloseHandle(file);
|
||
|
if( !success )
|
||
|
{
|
||
|
asIScriptContext *ctx = asGetActiveContext();
|
||
|
if( ctx )
|
||
|
ctx->SetException("Failed to get file creation date/time");
|
||
|
return CDateTime();
|
||
|
}
|
||
|
SYSTEMTIME tm;
|
||
|
FileTimeToSystemTime(&createTm, &tm);
|
||
|
return CDateTime(tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond);
|
||
|
#else
|
||
|
// Get the create date/time of the file
|
||
|
struct stat st;
|
||
|
if (stat(search.c_str(), &st) == -1)
|
||
|
{
|
||
|
asIScriptContext *ctx = asGetActiveContext();
|
||
|
if( ctx )
|
||
|
ctx->SetException("Failed to get file creation date/time");
|
||
|
return CDateTime();
|
||
|
}
|
||
|
tm *t = localtime(&st.st_ctime);
|
||
|
return CDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
CDateTime CScriptFileSystem::GetModifyDateTime(const string &path) const
|
||
|
{
|
||
|
string search;
|
||
|
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||
|
search = path;
|
||
|
else
|
||
|
search = currentPath + "/" + path;
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
// Windows uses UTF16 so it is necessary to convert the string
|
||
|
wchar_t bufUTF16[10000];
|
||
|
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||
|
|
||
|
// Get the last modify date/time of the file
|
||
|
FILETIME modifyTm;
|
||
|
HANDLE file = CreateFileW(bufUTF16, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||
|
BOOL success = GetFileTime(file, 0, 0, &modifyTm);
|
||
|
CloseHandle(file);
|
||
|
if( !success )
|
||
|
{
|
||
|
asIScriptContext *ctx = asGetActiveContext();
|
||
|
if( ctx )
|
||
|
ctx->SetException("Failed to get file modify date/time");
|
||
|
return CDateTime();
|
||
|
}
|
||
|
SYSTEMTIME tm;
|
||
|
FileTimeToSystemTime(&modifyTm, &tm);
|
||
|
return CDateTime(tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond);
|
||
|
#else
|
||
|
// Get the last modify date/time of the file
|
||
|
struct stat st;
|
||
|
if (stat(search.c_str(), &st) == -1)
|
||
|
{
|
||
|
asIScriptContext *ctx = asGetActiveContext();
|
||
|
if( ctx )
|
||
|
ctx->SetException("Failed to get file modify date/time");
|
||
|
return CDateTime();
|
||
|
}
|
||
|
tm *t = localtime(&st.st_mtime);
|
||
|
return CDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
END_AS_NAMESPACE
|