diff --git a/panda/src/express/config_express.cxx b/panda/src/express/config_express.cxx index 416cb4c140..07cf77941a 100644 --- a/panda/src/express/config_express.cxx +++ b/panda/src/express/config_express.cxx @@ -116,6 +116,15 @@ ConfigVariableInt multifile_encryption_iteration_count "be loaded quickly, without paying the cost of an expensive hash on " "each subfile in order to decrypt it.")); +ConfigVariableBool vfs_case_sensitive +("vfs-case-sensitive", false, + PRC_DESC("Set this true to make the VirtualFileSystem present the native " + "OS-provided filesystem as if it were a case-sensitive file " + "system, even if it is not (e.g. on Windows). This variable " + "has no effect if the native filesystem is already case-sensitive, " + "and it has no effect on mounted multifile systems, which are " + "always case-sensitive.")); + ConfigVariableBool use_vfs ("use-vfs", true, PRC_DESC("Set this true to use the VirtualFileSystem mechanism for loading " diff --git a/panda/src/express/config_express.h b/panda/src/express/config_express.h index 4a7b96dff7..1fd17c2693 100644 --- a/panda/src/express/config_express.h +++ b/panda/src/express/config_express.h @@ -78,6 +78,8 @@ extern ConfigVariableInt encryption_key_length; extern ConfigVariableInt encryption_iteration_count; extern ConfigVariableInt multifile_encryption_iteration_count; +extern ConfigVariableBool vfs_case_sensitive; + extern EXPCL_PANDAEXPRESS ConfigVariableBool use_vfs; extern EXPCL_PANDAEXPRESS ConfigVariableBool collect_tcp; diff --git a/panda/src/express/virtualFileMountSystem.cxx b/panda/src/express/virtualFileMountSystem.cxx index b1c34e6b8f..16b360690f 100644 --- a/panda/src/express/virtualFileMountSystem.cxx +++ b/panda/src/express/virtualFileMountSystem.cxx @@ -30,6 +30,20 @@ TypeHandle VirtualFileMountSystem::_type_handle; bool VirtualFileMountSystem:: has_file(const Filename &file) const { Filename pathname(_physical_filename, file); +#ifdef WIN32 + if (vfs_case_sensitive) { + Filename case_pathname = pathname; + if (!case_pathname.make_true_case()) { + return false; + } + if (case_pathname != pathname) { + express_cat.warning() + << "Filename is incorrect case: " << pathname + << " instead of " << case_pathname << "\n"; + return false; + } + } +#endif // WIN32 return pathname.exists(); } @@ -41,6 +55,14 @@ has_file(const Filename &file) const { //////////////////////////////////////////////////////////////////// bool VirtualFileMountSystem:: is_directory(const Filename &file) const { +#ifdef WIN32 + // First ensure that the file exists to validate its case. + if (vfs_case_sensitive) { + if (!has_file(file)) { + return false; + } + } +#endif // WIN32 Filename pathname(_physical_filename, file); return pathname.is_directory(); } @@ -53,6 +75,14 @@ is_directory(const Filename &file) const { //////////////////////////////////////////////////////////////////// bool VirtualFileMountSystem:: is_regular_file(const Filename &file) const { +#ifdef WIN32 + // First ensure that the file exists to validate its case. + if (vfs_case_sensitive) { + if (!has_file(file)) { + return false; + } + } +#endif // WIN32 Filename pathname(_physical_filename, file); return pathname.is_regular_file(); } @@ -67,6 +97,14 @@ is_regular_file(const Filename &file) const { //////////////////////////////////////////////////////////////////// istream *VirtualFileMountSystem:: open_read_file(const Filename &file) const { +#ifdef WIN32 + // First ensure that the file exists to validate its case. + if (vfs_case_sensitive) { + if (!has_file(file)) { + return NULL; + } + } +#endif // WIN32 Filename pathname(_physical_filename, file); pathname.set_binary(); ifstream *stream = new ifstream; @@ -113,6 +151,14 @@ get_file_size(const Filename &, istream *stream) const { //////////////////////////////////////////////////////////////////// bool VirtualFileMountSystem:: scan_directory(vector_string &contents, const Filename &dir) const { +#ifdef WIN32 + // First ensure that the file exists to validate its case. + if (vfs_case_sensitive) { + if (!has_file(dir)) { + return false; + } + } +#endif // WIN32 Filename pathname(_physical_filename, dir); return pathname.scan_directory(contents); }