diff --git a/code/DefaultIOStream.cpp b/code/DefaultIOStream.cpp index cce9af19d..487ba27ca 100644 --- a/code/DefaultIOStream.cpp +++ b/code/DefaultIOStream.cpp @@ -123,7 +123,8 @@ size_t DefaultIOStream::FileSize() const // https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file #if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) struct __stat64 fileStat; - int err = _stat64( mFilename.c_str(), &fileStat ); + //using fileno + fstat avoids having to handle the filename + int err = _fstat64( _fileno(mFile), &fileStat ); if (0 != err) return 0; mCachedSize = (size_t) (fileStat.st_size); diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 8687b0059..d83d2a79f 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -54,31 +54,49 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #endif +#ifdef _WIN32 +#include +#endif + using namespace Assimp; -// ------------------------------------------------------------------------------------------------ -// Constructor. -DefaultIOSystem::DefaultIOSystem() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor. -DefaultIOSystem::~DefaultIOSystem() -{ - // nothing to do here -} +// maximum path length +// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html +#ifdef PATH_MAX +# define PATHLIMIT PATH_MAX +#else +# define PATHLIMIT 4096 +#endif // ------------------------------------------------------------------------------------------------ // Tests for the existence of a file at the given path. bool DefaultIOSystem::Exists( const char* pFile) const { +#ifdef _WIN32 + wchar_t fileName16[PATHLIMIT]; + + bool isUnicode = IsTextUnicode(pFile, strlen(pFile), NULL); + if (isUnicode) { + + MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); + struct _stat64 filestat; + if (0 != _wstat64(fileName16, &filestat)) { + return false; + } + } else { + FILE* file = ::fopen(pFile, "rb"); + if (!file) + return false; + + ::fclose(file); + } +#else FILE* file = ::fopen( pFile, "rb"); if( !file) return false; ::fclose( file); +#endif return true; } @@ -88,10 +106,22 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) { ai_assert(NULL != strFile); ai_assert(NULL != strMode); - - FILE* file = ::fopen( strFile, strMode); - if( NULL == file) - return NULL; + FILE* file; +#ifdef _WIN32 + wchar_t fileName16[PATHLIMIT]; + bool isUnicode = IsTextUnicode(strFile, strlen(strFile), NULL ); + if (isUnicode) { + MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT); + std::string mode8(strMode); + file = ::_wfopen(fileName16, std::wstring(mode8.begin(), mode8.end()).c_str()); + } else { + file = ::fopen(strFile, strMode); + } +#else + file = ::fopen(strFile, strMode); +#endif + if (nullptr == file) + return nullptr; return new DefaultIOStream(file, (std::string) strFile); } @@ -121,32 +151,47 @@ bool IOSystem::ComparePaths (const char* one, const char* second) const return !ASSIMP_stricmp(one,second); } -// maximum path length -// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html -#ifdef PATH_MAX -# define PATHLIMIT PATH_MAX -#else -# define PATHLIMIT 4096 -#endif - // ------------------------------------------------------------------------------------------------ // Convert a relative path into an absolute path -inline void MakeAbsolutePath (const char* in, char* _out) +inline static void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); - char* ret; #if defined( _MSC_VER ) || defined( __MINGW32__ ) - ret = ::_fullpath( _out, in, PATHLIMIT ); + bool isUnicode = IsTextUnicode(in, strlen(in), NULL); + if (isUnicode) { + wchar_t out16[PATHLIMIT]; + wchar_t in16[PATHLIMIT]; + MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, -1, out16, PATHLIMIT); + wchar_t* ret = ::_wfullpath(out16, in16, PATHLIMIT); + if (ret) { + WideCharToMultiByte(CP_UTF8, MB_PRECOMPOSED, out16, -1, _out, PATHLIMIT, nullptr, nullptr); + } + if (!ret) { + // preserve the input path, maybe someone else is able to fix + // the path before it is accessed (e.g. our file system filter) + DefaultLogger::get()->warn("Invalid path: " + std::string(in)); + strcpy(_out, in); + } + + } else { + char* ret = :: _fullpath(_out, in, PATHLIMIT); + if (!ret) { + // preserve the input path, maybe someone else is able to fix + // the path before it is accessed (e.g. our file system filter) + DefaultLogger::get()->warn("Invalid path: " + std::string(in)); + strcpy(_out, in); + } + } #else // use realpath - ret = realpath(in, _out); -#endif + char* ret = realpath(in, _out); if(!ret) { // preserve the input path, maybe someone else is able to fix // the path before it is accessed (e.g. our file system filter) DefaultLogger::get()->warn("Invalid path: "+std::string(in)); strcpy(_out,in); } +#endif } // ------------------------------------------------------------------------------------------------ diff --git a/include/assimp/DefaultIOSystem.h b/include/assimp/DefaultIOSystem.h index d7cf031cf..718f5f4a5 100644 --- a/include/assimp/DefaultIOSystem.h +++ b/include/assimp/DefaultIOSystem.h @@ -52,12 +52,6 @@ namespace Assimp { class ASSIMP_API DefaultIOSystem : public IOSystem { public: - /** Constructor. */ - DefaultIOSystem(); - - /** Destructor. */ - ~DefaultIOSystem(); - // ------------------------------------------------------------------- /** Tests for the existence of a file at the given path. */ bool Exists( const char* pFile) const;