From 827c9f587d3f6df2cf0697f3705a160dbaaa14b5 Mon Sep 17 00:00:00 2001 From: Pavel Kovalenko Date: Sun, 2 Nov 2014 19:40:45 +0300 Subject: [PATCH] Add initial support for 'external' filesystem. --- res/gamedata/scripts/lua_help.script | 10 +++ src/utils/xrCompress/xrCompressDifference.cpp | 17 +++-- src/xrCore/LocatorAPI.cpp | 76 ++++++++++++++----- src/xrCore/LocatorAPI.h | 39 ++++++++-- src/xrCore/stdafx.h | 1 + src/xrGame/fs_registrator_script.cpp | 13 +++- 6 files changed, 123 insertions(+), 33 deletions(-) diff --git a/res/gamedata/scripts/lua_help.script b/res/gamedata/scripts/lua_help.script index 9e40e9faa75..6881140bf73 100644 --- a/res/gamedata/scripts/lua_help.script +++ b/res/gamedata/scripts/lua_help.script @@ -2628,6 +2628,12 @@ C++ class CLevelChanger : CGameObject { }; +C++ class FileStatus +{ + bool Exists const; + bool External const; +}; + C++ class FS { const FS_ClampExt = 4; const FS_ListFiles = 1; @@ -2640,6 +2646,10 @@ C++ class FS { const FS_sort_by_size_down = 3; const FS_sort_by_size_up = 2; + const FSType_Virtual = 1; + const FSType_External = 2; + const FSType_Any = 3; + function get_file_age(string); function file_length(string); diff --git a/src/utils/xrCompress/xrCompressDifference.cpp b/src/utils/xrCompress/xrCompressDifference.cpp index c7d8f92b37a..1dc98248247 100644 --- a/src/utils/xrCompress/xrCompressDifference.cpp +++ b/src/utils/xrCompress/xrCompressDifference.cpp @@ -25,9 +25,10 @@ struct file_comparer{ // xr_strcpy(m_short_name,c+xr_strlen(arget_folder)+1); xr_strcpy(m_full_name,c); - const CLocatorAPI::file* f = m_fs_new->exist("$target_folder$",m_full_name); - if(f) - m_file_size = f->size_real; + string_path path; + m_fs_new->update_path(path, "$target_folder$", m_full_name); + if (m_fs_new->exist(path)) + m_file_size = m_fs_new->file_length(path); } bool operator ()(char* o){ @@ -40,10 +41,12 @@ struct file_comparer{ if( !m_flags.test(eDontCheckFileSize) ){ //compare file size - const CLocatorAPI::file* f = m_fs_old->exist("$target_folder$",o); - u32 file_size = f->size_real; - - if ( (f->vfs==0xffffffff) && (file_size != m_file_size) ) + string_path path; + m_fs_old->update_path(path, "$target_folder$", o); + if (!m_fs_old->exist(path)) + return false; + auto fileDesc = m_fs_old->GetFileDesc(path); + if (fileDesc->vfs == 0xffffffff && fileDesc->size_real != m_file_size) return false; }; //compare file crc diff --git a/src/xrCore/LocatorAPI.cpp b/src/xrCore/LocatorAPI.cpp index ed800ce36d5..814ecb7fc6e 100644 --- a/src/xrCore/LocatorAPI.cpp +++ b/src/xrCore/LocatorAPI.cpp @@ -203,7 +203,16 @@ CLocatorAPI::~CLocatorAPI() _dump_open_files(1); } -void CLocatorAPI::Register(LPCSTR name, u32 vfs, u32 crc, u32 ptr, u32 size_real, u32 size_compressed, u32 modif) +const CLocatorAPI::file* CLocatorAPI::RegisterExternal(const char* name) +{ + struct stat buffer; + if (stat(name, &buffer) == -1) + return nullptr; + return Register(name, u32(-1), 0, 0, buffer.st_size, buffer.st_size, u32(buffer.st_mtime)); +} + +const CLocatorAPI::file* CLocatorAPI::Register(LPCSTR name, u32 vfs, u32 crc, u32 ptr, + u32 size_real, u32 size_compressed, u32 modif) { //Msg("Register[%d] [%s]",vfs,name); string256 temp_file_name; @@ -231,7 +240,7 @@ void CLocatorAPI::Register(LPCSTR name, u32 vfs, u32 crc, u32 ptr, u32 size_real // sad but true, performance option // correct way is to erase and then insert new record: const_cast(*I) = desc; - return; + return &*I; } else { @@ -239,7 +248,7 @@ void CLocatorAPI::Register(LPCSTR name, u32 vfs, u32 crc, u32 ptr, u32 size_real } // otherwise insert file - m_files.insert(desc); + auto result = m_files.insert(desc).first; // Try to register folder(s) string_path temp; @@ -265,6 +274,7 @@ void CLocatorAPI::Register(LPCSTR name, u32 vfs, u32 crc, u32 ptr, u32 size_real xr_strcpy(temp, sizeof(temp), folder); if (xr_strlen(temp)) temp[xr_strlen(temp) - 1] = 0; } + return &*result; } IReader* open_chunk(void* ptr, u32 ID) @@ -874,31 +884,50 @@ void CLocatorAPI::_destroy() m_archives.clear(); } -const CLocatorAPI::file* CLocatorAPI::exist(const char* fn) +const CLocatorAPI::file* CLocatorAPI::GetFileDesc(const char* path) { - files_it it = file_find_it(fn); - return (it != m_files.end()) ? &(*it) : 0; + auto it = file_find_it(path); + return it != m_files.end() ? &*it : nullptr; +} + +FileStatus CLocatorAPI::exist(const char* fn, FSType fsType /*= FSType::Virtual*/) +{ + if ((fsType | FSType::Virtual) == FSType::Virtual) + { + files_it it = file_find_it(fn); + if (it != m_files.end()) + return FileStatus(true, false); + } + if ((fsType | FSType::External) == FSType::External) + { + struct stat buffer; + buffer.st_size; + return FileStatus(stat(fn, &buffer) == 0, true); + } + return FileStatus(false, false); } -const CLocatorAPI::file* CLocatorAPI::exist(const char* path, const char* name) +FileStatus CLocatorAPI::exist(const char* path, const char* name, FSType fsType /*= FSType::Virtual*/) { string_path temp; update_path(temp, path, name); - return exist(temp); + return exist(temp, fsType); } -const CLocatorAPI::file* CLocatorAPI::exist(string_path& fn, LPCSTR path, LPCSTR name) +FileStatus CLocatorAPI::exist(string_path& fn, LPCSTR path, LPCSTR name, + FSType fsType /*= FSType::Virtual*/) { update_path(fn, path, name); - return exist(fn); + return exist(fn, fsType); } -const CLocatorAPI::file* CLocatorAPI::exist(string_path& fn, LPCSTR path, LPCSTR name, LPCSTR ext) +FileStatus CLocatorAPI::exist(string_path& fn, LPCSTR path, LPCSTR name, LPCSTR ext, + FSType fsType /*= FSType::Virtual*/) { string_path nm; strconcat(sizeof(nm), nm, name, ext); update_path(fn, path, nm); - return exist(fn); + return exist(fn, fsType); } xr_vector* CLocatorAPI::file_list_open(const char* initial, const char* folder, u32 flags) @@ -1306,13 +1335,19 @@ bool CLocatorAPI::check_for_file(LPCSTR path, LPCSTR _fname, string_path& fname, // Search entry file desc_f; desc_f.name = fname; - files_it I = m_files.find(desc_f); if (I == m_files.end()) - return (false); - + { + if (!exist(fname, FSType::External)) + return false; + const file* extFile = RegisterExternal(fname); + if (!extFile) + return false; + desc = extFile; + } + else + desc = &*I; ++dwOpenCounter; - desc = &*I; return (true); } @@ -1546,8 +1581,13 @@ void CLocatorAPI::file_rename(LPCSTR src, LPCSTR dest, bool bOwerwrite) int CLocatorAPI::file_length(LPCSTR src) { - files_it I = file_find_it(src); - return (I != m_files.end()) ? I->size_real : -1; + files_it it = file_find_it(src); + if (it != m_files.end()) + return it->size_real; + struct stat buffer; + if (stat(src, &buffer) != -1) + return buffer.st_size; + return -1; } bool CLocatorAPI::path_exist(LPCSTR path) diff --git a/src/xrCore/LocatorAPI.h b/src/xrCore/LocatorAPI.h index 54c0f0d1816..2dfb4a34476 100644 --- a/src/xrCore/LocatorAPI.h +++ b/src/xrCore/LocatorAPI.h @@ -10,11 +10,35 @@ #pragma warning(disable:4995) #include #pragma warning(pop) - +#include "Common/Util.hpp" #include "LocatorAPI_defs.h" class XRCORE_API CStreamReader; +enum class FSType +{ + Virtual = 1, + External = 2, + Any = Virtual | External, +}; + +IMPLEMENT_ENUM_FLAG_OPERATORS(FSType, int); + +class FileStatus +{ +public: + bool Exists; + bool External; // File can be accessed only as external + + inline FileStatus(bool exists, bool external) + { + Exists = exists; + External = external; + } + + inline operator bool() { return Exists; } +}; + class XRCORE_API CLocatorAPI { friend class FS_Path; @@ -69,7 +93,8 @@ class XRCORE_API CLocatorAPI xrCriticalSection m_auth_lock; u64 m_auth_code; - void Register(LPCSTR name, u32 vfs, u32 crc, u32 ptr, u32 size_real, u32 size_compressed, u32 modif); + const file* RegisterExternal(const char* name); + const file* Register(LPCSTR name, u32 vfs, u32 crc, u32 ptr, u32 size_real, u32 size_compressed, u32 modif); void ProcessArchive(LPCSTR path); void ProcessOne(LPCSTR path, const _finddata_t& entry); bool Recurse(LPCSTR path); @@ -136,11 +161,13 @@ class XRCORE_API CLocatorAPI IWriter* w_open_ex(LPCSTR initial, LPCSTR N); IC IWriter* w_open_ex(LPCSTR N) { return w_open_ex(0, N); } void w_close(IWriter*& S); + // For registered files only + const file* GetFileDesc(const char* path); - const file* exist(LPCSTR N); - const file* exist(LPCSTR path, LPCSTR name); - const file* exist(string_path& fn, LPCSTR path, LPCSTR name); - const file* exist(string_path& fn, LPCSTR path, LPCSTR name, LPCSTR ext); + FileStatus exist(LPCSTR N, FSType fsType = FSType::Virtual); + FileStatus exist(LPCSTR path, LPCSTR name, FSType fsType = FSType::Virtual); + FileStatus exist(string_path& fn, LPCSTR path, LPCSTR name, FSType fsType = FSType::Virtual); + FileStatus exist(string_path& fn, LPCSTR path, LPCSTR name, LPCSTR ext, FSType fsType = FSType::Virtual); BOOL can_write_to_folder(LPCSTR path); BOOL can_write_to_alias(LPCSTR path); diff --git a/src/xrCore/stdafx.h b/src/xrCore/stdafx.h index 8e496b17cad..4fd830eb389 100644 --- a/src/xrCore/stdafx.h +++ b/src/xrCore/stdafx.h @@ -10,6 +10,7 @@ #include "xrCore.h" #include "xrCore_platform.h" +#include "Common/Util.hpp" //.#include "../../Include/xrAPI/xrAPI.h" #endif diff --git a/src/xrGame/fs_registrator_script.cpp b/src/xrGame/fs_registrator_script.cpp index 392e2cc07d2..a19f5753305 100644 --- a/src/xrGame/fs_registrator_script.cpp +++ b/src/xrGame/fs_registrator_script.cpp @@ -189,6 +189,9 @@ void fs_registrator::script_register(lua_State *L) .def_readonly("size_compressed", &CLocatorAPI::file::size_compressed) .def_readonly("modif", &CLocatorAPI::file::modif), + class_("FileStatus") + .def_readonly("Exists", &FileStatus::Exists) + .def_readonly("External", &FileStatus::External), class_("FS") .enum_("FS_sort_mode") @@ -207,6 +210,12 @@ void fs_registrator::script_register(lua_State *L) value("FS_ClampExt", int(FS_ClampExt)), value("FS_RootOnly", int(FS_RootOnly)) ] + .enum_("FSType") + [ + value("FSType_Virtual", int(FSType::Virtual)), + value("FSType_External", int(FSType::External)), + value("FSType_Any", int(FSType::Any)) + ] .def("path_exist", &CLocatorAPI::path_exist) .def("update_path", &update_path_script) .def("get_path", &CLocatorAPI::get_path) @@ -222,8 +231,8 @@ void fs_registrator::script_register(lua_State *L) .def("file_length", &CLocatorAPI::file_length) .def("file_copy", &CLocatorAPI::file_copy) - .def("exist", (const CLocatorAPI::file* (CLocatorAPI::*)(LPCSTR)) (&CLocatorAPI::exist)) - .def("exist", (const CLocatorAPI::file* (CLocatorAPI::*)(LPCSTR, LPCSTR)) (&CLocatorAPI::exist)) + .def("exist", (FileStatus (CLocatorAPI::*)(LPCSTR, FSType))(&CLocatorAPI::exist)) + .def("exist", (FileStatus (CLocatorAPI::*)(LPCSTR, LPCSTR, FSType))(&CLocatorAPI::exist)) .def("get_file_age", &CLocatorAPI::get_file_age) .def("get_file_age_str", &get_file_age_str)