From 25dc8660efedecfd9f021142ac1e4ff3639e80d4 Mon Sep 17 00:00:00 2001 From: Rye Date: Tue, 30 Dec 2025 11:39:16 -0500 Subject: Clean up LLFile and LLFilesystem operations to reduce temporaries allocations and utf8->utf16 conversions Fix LLFile::tmpdir failing when temp directory is located in a unicode path on windows Add Tracy profiler tagging to LLFile that's disabled by default Replace LLFile::utf8StringToWstring with our fsyspath std::filesystem::path adapter Introduce std::filesystem::path to llifstream/llofstream wrappers Add move operators to fsyspath to match copy operator Restore LLUniqueFile RAII class for direct c file io wrapping and reducing merge conflicts with downstream code that may depend upon it Signed-off-by: Rye --- indra/llappearance/llpolymesh.cpp | 2 +- indra/llcommon/fsyspath.h | 4 +- indra/llcommon/llcrc.cpp | 2 +- indra/llcommon/llcrc.h | 2 +- indra/llcommon/llfile.cpp | 290 +++++++---------- indra/llcommon/llfile.h | 465 +++++++++++++++++++++++----- indra/llcommon/llprocessor.cpp | 4 +- indra/llcommon/llprofilercategories.h | 9 + indra/llcommon/llsys.cpp | 6 +- indra/llcommon/tests/llfile_test.cpp | 115 ++++--- indra/llfilesystem/lldir.cpp | 15 +- indra/llfilesystem/lldir.h | 2 +- indra/llfilesystem/lldir_linux.cpp | 18 -- indra/llfilesystem/lldir_linux.h | 1 - indra/llfilesystem/lldir_mac.cpp | 8 - indra/llfilesystem/lldir_mac.h | 1 - indra/llfilesystem/lldir_win32.cpp | 7 - indra/llfilesystem/lldir_win32.h | 1 - indra/llfilesystem/llfilesystem.cpp | 81 ++--- indra/llfilesystem/llfilesystem.h | 5 +- indra/llfilesystem/tests/lldir_test.cpp | 2 +- indra/llimage/llimagedimensionsinfo.cpp | 2 +- indra/llimage/llimagetga.cpp | 2 +- indra/llmessage/llassetstorage.cpp | 2 +- indra/llmessage/lltransfersourcefile.cpp | 2 +- indra/llmessage/lltransfertargetfile.cpp | 2 +- indra/llmessage/llxfer_file.cpp | 16 +- indra/llmessage/message.cpp | 4 +- indra/llmessage/tests/lldatapacker_test.cpp | 4 +- indra/llrender/llshadermgr.cpp | 4 +- indra/llui/lluicolortable.cpp | 2 +- indra/llui/llxuiparser.cpp | 6 +- indra/llxml/llcontrol.cpp | 2 +- indra/llxml/llxmlparser.cpp | 4 +- indra/newview/llconversationlog.cpp | 4 +- indra/newview/lldrawpoolbump.cpp | 2 +- indra/newview/llfloaterpreference.cpp | 10 +- indra/newview/llfloateruipreview.cpp | 2 +- indra/newview/llinventorymodel.cpp | 4 +- indra/newview/llkeyconflict.cpp | 2 +- indra/newview/lllogchat.cpp | 12 +- indra/newview/llmutelist.cpp | 8 +- indra/newview/llpreviewnotecard.cpp | 4 +- indra/newview/llpreviewscript.cpp | 4 +- indra/newview/llstartup.cpp | 6 +- indra/newview/lltoolbarview.cpp | 2 +- indra/newview/llviewerassetstorage.cpp | 4 +- indra/newview/llviewerinput.cpp | 2 +- indra/newview/llviewermenufile.cpp | 2 +- indra/newview/llviewerstatsrecorder.cpp | 2 +- 50 files changed, 678 insertions(+), 484 deletions(-) diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index d5323e0b84..b579dc007b 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -280,7 +280,7 @@ bool LLPolyMeshSharedData::loadMesh( const std::string& fileName ) LL_ERRS() << "Filename is Empty!" << LL_ENDL; return false; } - LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/ + LLFILE* fp = LLFile::fopen(fileName, TEXT("rb")); /*Flawfinder: ignore*/ if (!fp) { LLError::LLUserWarningMsg::showMissingFiles(); diff --git a/indra/llcommon/fsyspath.h b/indra/llcommon/fsyspath.h index 2c900c02a7..237d99ae86 100644 --- a/indra/llcommon/fsyspath.h +++ b/indra/llcommon/fsyspath.h @@ -57,7 +57,7 @@ class fsyspath: public std::filesystem::path public: // default - fsyspath() {} + fsyspath() = default; // construct from UTF-8 encoded string fsyspath(const std::string& path): fsyspath(std::string_view(path)) {} fsyspath(const char* path): fsyspath(std::string_view(path)) {} @@ -66,8 +66,10 @@ public: {} // construct from existing path fsyspath(const super& path): super(path) {} + fsyspath(super&& path) : super(std::move(path)) {} fsyspath& operator=(const super& p) { super::operator=(p); return *this; } + fsyspath& operator=(super&& p) { super::operator=(std::move(p)); return *this; } fsyspath& operator=(const std::string& p) { return (*this) = std::string_view(p); } fsyspath& operator=(const char* p) { return (*this) = std::string_view(p); } fsyspath& operator=(std::string_view p) diff --git a/indra/llcommon/llcrc.cpp b/indra/llcommon/llcrc.cpp index d79d06e2a2..f836a12c35 100644 --- a/indra/llcommon/llcrc.cpp +++ b/indra/llcommon/llcrc.cpp @@ -166,7 +166,7 @@ void LLCRC::update(const std::string& filename) return; } - FILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ + FILE* fp = LLFile::fopen(filename, TEXT("rb")); /* Flawfinder: ignore */ if (fp) { diff --git a/indra/llcommon/llcrc.h b/indra/llcommon/llcrc.h index a3bde47780..cbf4cf4e75 100644 --- a/indra/llcommon/llcrc.h +++ b/indra/llcommon/llcrc.h @@ -36,7 +36,7 @@ // example (don't try this at work kids): // // LLCRC crc; -// FILE* fp = LLFile::fopen(filename,"rb"); +// FILE* fp = LLFile::fopen(filename,TEXT("rb")); // while(!feof(fp)) { // crc.update(fgetc(fp)); // } diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index 0ceb2eb03b..114df29f6e 100755 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -226,7 +226,7 @@ static void find_locking_process(const std::string& filename) } #endif // LL_WINDOWS hack to identify processes holding file open -static int warnif(std::string_view desc, const std::string& filename, int rc, int suppress_warning = 0) +static int warnif(std::string_view desc, const std::filesystem::path& filename, int rc, int suppress_warning = 0) { if (rc < 0) { @@ -252,7 +252,7 @@ static int warnif(std::string_view desc, const std::string& filename, int rc, in return rc; } -static int warnif(std::string_view desc, const std::string& filename, const std::error_code& ec, int suppress_warning = 0) +static int warnif(std::string_view desc, const std::filesystem::path& filename, const std::error_code& ec, int suppress_warning = 0) { if (ec) { @@ -506,8 +506,9 @@ inline bool are_open_mode_flags_invalid(std::ios_base::openmode omode) //---------------------------------------------------------------------------------------- // class member functions //---------------------------------------------------------------------------------------- -int LLFile::open(const std::string& filename, std::ios_base::openmode omode, std::error_code& ec, int perm) +int LLFile::open(const std::filesystem::path& file_path, std::ios_base::openmode omode, std::error_code& ec, int perm) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; close(ec); if (are_open_mode_flags_invalid(omode)) { @@ -519,14 +520,13 @@ int LLFile::open(const std::string& filename, std::ios_base::openmode omode, std create = decode_open_create_flags(omode), attributes = decode_attributes(omode, perm); - std::wstring file_path = utf8StringToWstring(filename); - mHandle = CreateFileW(file_path.c_str(), access, share, nullptr, create, attributes, nullptr); + mHandle = CreateFileW(file_path.native().c_str(), access, share, nullptr, create, attributes, nullptr); // The dwShareMode = share parameter takes care of locking the file for other processes if indicated, // no need to do anything else for file locking here #else int oflags = decode_open_mode(omode); int lmode = omode & LLFile::lock_mask; - mHandle = ::open(filename.c_str(), oflags, perm); + mHandle = ::open(file_path.native().c_str(), oflags, perm); if (mHandle != InvalidHandle && lmode && lock(lmode | LLFile::noblock, ec) != 0) { close(); @@ -549,6 +549,7 @@ int LLFile::open(const std::string& filename, std::ios_base::openmode omode, std S64 LLFile::size(std::error_code& ec) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; #if LL_WINDOWS LARGE_INTEGER value = { 0 }; if (GetFileSizeEx(mHandle, &value)) @@ -570,6 +571,7 @@ S64 LLFile::size(std::error_code& ec) S64 LLFile::tell(std::error_code& ec) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; #if LL_WINDOWS LARGE_INTEGER value = { 0 }; if (SetFilePointerEx(mHandle, value, &value, FILE_CURRENT)) @@ -595,6 +597,7 @@ int LLFile::seek(S64 pos, std::error_code& ec) int LLFile::seek(S64 offset, std::ios_base::seekdir dir, std::error_code& ec) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; S64 newOffset = 0; #if LL_WINDOWS DWORD seekdir = seek_mode_from_dir(dir); @@ -620,6 +623,7 @@ inline DWORD next_buffer_size(S64 nbytes) S64 LLFile::read(void* buffer, S64 nbytes, std::error_code& ec) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; if (nbytes == 0) { // Nothing to do @@ -660,6 +664,7 @@ S64 LLFile::read(void* buffer, S64 nbytes, std::error_code& ec) S64 LLFile::write(const void* buffer, S64 nbytes, std::error_code& ec) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; if (nbytes == 0) { // Nothing to do here @@ -705,6 +710,7 @@ S64 LLFile::write(const void* buffer, S64 nbytes, std::error_code& ec) S64 LLFile::printf(const char* fmt, ...) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; va_list args1; va_start(args1, fmt); va_list args2; @@ -732,6 +738,7 @@ S64 LLFile::printf(const char* fmt, ...) int LLFile::lock(int mode, std::error_code& ec) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; #if LL_WINDOWS if (!(mode & LLFile::lock_mask)) { @@ -765,6 +772,7 @@ int LLFile::lock(int mode, std::error_code& ec) int LLFile::close(std::error_code& ec) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; if (mHandle != InvalidHandle) { llfile_handle_t handle = InvalidHandle; @@ -792,8 +800,9 @@ int LLFile::close() //---------------------------------------------------------------------------------------- // static -LLFILE* LLFile::fopen(const std::string& filename, const char* mode, int lmode) +LLFILE* LLFile::fopen(const std::filesystem::path& file_path, const fopen_flags_t* mode, int lmode) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; LLFILE* file; #if LL_WINDOWS int shflag = _SH_DENYNO; @@ -806,11 +815,9 @@ LLFILE* LLFile::fopen(const std::string& filename, const char* mode, int lmode) shflag = _SH_DENYWR; break; } - std::wstring file_path = utf8StringToWstring(filename); - std::wstring utf16mode = ll_convert(std::string(mode)); - file = _wfsopen(file_path.c_str(), utf16mode.c_str(), shflag); + file = _wfsopen(file_path.native().c_str(), mode, shflag); #else - file = ::fopen(filename.c_str(), mode); + file = ::fopen(file_path.native().c_str(), mode); if (file && (lmode & (LLFile::lock_mask))) { // Rather fail on a sharing conflict than block @@ -827,6 +834,7 @@ LLFILE* LLFile::fopen(const std::string& filename, const char* mode, int lmode) // static int LLFile::close(LLFILE* file) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; int ret_value = 0; if (file) { @@ -836,17 +844,11 @@ int LLFile::close(LLFILE* file) } // static -std::string LLFile::getContents(const std::string& filename) -{ - std::error_code ec; - return getContents(filename, ec); -} - -// static -std::string LLFile::getContents(const std::string& filename, std::error_code& ec) +std::string LLFile::getContents(const std::filesystem::path& file_path, std::error_code& ec) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; std::string buffer; - LLFile file(filename, LLFile::in | LLFile::binary, ec); + LLFile file(file_path, LLFile::in | LLFile::binary, ec); if (file) { S64 length = file.size(ec); @@ -864,48 +866,41 @@ std::string LLFile::getContents(const std::string& filename, std::error_code& ec } // static -int LLFile::mkdir(const std::string& dirname) +int LLFile::mkdir(const std::filesystem::path& file_path) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; std::error_code ec; - std::filesystem::path file_path = utf8StringToPath(dirname); // We often use mkdir() to ensure the existence of a directory that might // already exist. There is no known case in which we want to call out as // an error the requested directory already existing. std::filesystem::create_directory(file_path, ec); // The return value is only true if the directory was actually created. // But if it already existed, ec still indicates success. - return warnif("mkdir", dirname, ec); + return warnif("mkdir", file_path, ec); } // static -int LLFile::remove(const std::string& filename, int suppress_warning) +int LLFile::remove(const std::filesystem::path& file_path, int suppress_warning) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; std::error_code ec; - std::filesystem::path file_path = utf8StringToPath(filename); std::filesystem::remove(file_path, ec); - return warnif("remove", filename, ec, suppress_warning); + return warnif("remove", file_path, ec, suppress_warning); } // static -int LLFile::rename(const std::string& filename, const std::string& newname, int suppress_warning) +int LLFile::rename(const std::filesystem::path& file_path, const std::filesystem::path& new_path, int suppress_warning) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; std::error_code ec; - std::filesystem::path file_path = utf8StringToPath(filename); - std::filesystem::path new_path = utf8StringToPath(newname); std::filesystem::rename(file_path, new_path, ec); - return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, ec, suppress_warning); -} - -// static -S64 LLFile::read(const std::string& filename, void* buf, S64 offset, S64 nbytes) -{ - std::error_code ec; - return read(filename, buf, offset, nbytes, ec); + return warnif("rename", file_path, ec, suppress_warning); } // static -S64 LLFile::read(const std::string& filename, void* buf, S64 offset, S64 nbytes, std::error_code& ec) +S64 LLFile::read(const std::filesystem::path& file_path, void* buf, S64 offset, S64 nbytes, std::error_code& ec) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; // if number of bytes is 0 or less there is nothing to do here if (nbytes <= 0) { @@ -921,7 +916,7 @@ S64 LLFile::read(const std::string& filename, void* buf, S64 offset, S64 nbytes, { std::ios_base::openmode omode = LLFile::in | LLFile::binary; - LLFile file(filename, omode, ec); + LLFile file(file_path, omode, ec); if (!ec && (bool)file) { if (offset > 0) @@ -939,19 +934,13 @@ S64 LLFile::read(const std::string& filename, void* buf, S64 offset, S64 nbytes, } } } - return warnif("read from file failed", filename, ec); + return warnif("read from file failed", file_path, ec); } // static -S64 LLFile::write(const std::string& filename, const void* buf, S64 offset, S64 nbytes) -{ - std::error_code ec; - return write(filename, buf, offset, nbytes, ec); -} - -// static -S64 LLFile::write(const std::string& filename, const void* buf, S64 offset, S64 nbytes, std::error_code& ec) +S64 LLFile::write(const std::filesystem::path& file_path, const void* buf, S64 offset, S64 nbytes, std::error_code& ec) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; // if number of bytes is 0 or less there is nothing to do here if (nbytes <= 0) { @@ -971,7 +960,7 @@ S64 LLFile::write(const std::string& filename, const void* buf, S64 offset, S64 omode |= LLFile::app; } - LLFile file(filename, omode, ec); + LLFile file(file_path, omode, ec); if (!ec && (bool)file) { if (offset > 0) @@ -989,99 +978,52 @@ S64 LLFile::write(const std::string& filename, const void* buf, S64 offset, S64 } } } - return warnif("write to file failed", filename, ec); + return warnif("write to file failed", file_path, ec); } // static -bool LLFile::copy(const std::string& source, const std::string& target) +bool LLFile::copy(const std::filesystem::path& source_path, const std::filesystem::path& target_path, std::filesystem::copy_options options, std::error_code& ec) { - std::error_code ec; - return copy(source, target, std::filesystem::copy_options::overwrite_existing, ec); -} - -// static -bool LLFile::copy(const std::string& source, const std::string& target, std::filesystem::copy_options options, std::error_code& ec) -{ - std::filesystem::path source_path = utf8StringToPath(source); - std::filesystem::path target_path = utf8StringToPath(target); + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; bool copied = std::filesystem::copy_file(source_path, target_path, options, ec); if (!copied) { - warnif(STRINGIZE("copy failed, to '" << target << "' from"), source, ec); + warnif(STRINGIZE("copy failed, to '" << target_path << "' from"), source_path, ec); } return copied; } // static -int LLFile::stat(const std::string& filename, llstat* filestatus, const char *fname, int suppress_warning) +int LLFile::stat(const std::filesystem::path& file_path, llstat* filestatus, const char *fname, int suppress_warning) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; #if LL_WINDOWS - std::wstring file_path = utf8StringToWstring(filename); - int rc = _wstat64(file_path.c_str(), filestatus); + int rc = _wstat64(file_path.native().c_str(), filestatus); #else - int rc = ::stat(filename.c_str(), filestatus); + int rc = ::stat(file_path.native().c_str(), filestatus); #endif - return warnif(fname ? fname : "stat", filename, rc, suppress_warning); + return warnif(fname ? fname : "stat", file_path, rc, suppress_warning); } // static -std::time_t LLFile::getCreationTime(const std::string& filename, int suppress_warning) -{ - // As of C++20 there is no functionality in std::filesystem to retrieve this information - llstat filestat; - int rc = stat(filename, &filestat, "getCreationTime", suppress_warning); - if (rc == 0) - { -#if LL_DARWIN - return filestat.st_birthtime; -#else - // Linux stat() doesn't have a creation/birth time (st_ctime really is the last status - // change or inode attributes change) unless we would use statx() instead. But that is - // a major effort, which would require Linux specific changes to LLFile::stat() above - // and possibly adaptions for other platforms that we leave for a later exercise if it - // is ever desired. - return filestat.st_ctime; -#endif - } - return 0; -} - -// static -std::time_t LLFile::getModificationTime(const std::string& filename, int suppress_warning) -{ - // tried to use std::filesystem::last_write_time() but the whole std::chrono infrastructure is as of - // C++20 still not fully implemented on all platforms. Specifically MacOS C++20 seems lacking here, - // and Windows requires a roundabout through std::chrono::utc_clock to then get a - // std::chrono::system_clock that can return a more useful time_t. - // So we take the easy way out in a similar way as with getCreationTime(). - llstat filestat; - int rc = stat(filename, &filestat, "getModificationTime", suppress_warning); - if (rc == 0) - { - return filestat.st_mtime; - } - return 0; -} - -// static -S64 LLFile::size(const std::string& filename, int suppress_warning) +S64 LLFile::size(const std::filesystem::path& file_path, int suppress_warning) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; std::error_code ec; - std::filesystem::path file_path = utf8StringToPath(filename); std::intmax_t size = static_cast(std::filesystem::file_size(file_path, ec)); if (ec) { - warnif("size", filename, ec, suppress_warning); + warnif("size", file_path, ec, suppress_warning); return 0; } return size; } // static -std::filesystem::file_status LLFile::getStatus(const std::string& filename, bool dontFollowSymLink, int suppress_warning) +std::filesystem::file_status LLFile::getStatus(const std::filesystem::path& file_path, bool dontFollowSymLink, int suppress_warning) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; std::error_code ec; - std::filesystem::path file_path = utf8StringToPath(filename); std::filesystem::file_status status; if (dontFollowSymLink) { @@ -1091,100 +1033,43 @@ std::filesystem::file_status LLFile::getStatus(const std::string& filename, bool { status = std::filesystem::status(file_path, ec); } - warnif("getStatus()", filename, ec, suppress_warning); + warnif("getStatus()", file_path, ec, suppress_warning); return status; } -// static -bool LLFile::exists(const std::string& filename) -{ - std::filesystem::file_status status = getStatus(filename); - return std::filesystem::exists(status); -} - -// static -bool LLFile::isdir(const std::string& filename) -{ - std::filesystem::file_status status = getStatus(filename); - return std::filesystem::is_directory(status); -} - -// static -bool LLFile::isfile(const std::string& filename) -{ - std::filesystem::file_status status = getStatus(filename); - return std::filesystem::is_regular_file(status); -} - -// static -bool LLFile::islink(const std::string& filename) -{ - std::filesystem::file_status status = getStatus(filename, true); - return std::filesystem::is_symlink(status); -} - // static const std::string& LLFile::tmpdir() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE; static std::string temppath; if (temppath.empty()) { - temppath = std::filesystem::temp_directory_path().string(); - } - #if LL_WINDOWS - char sep = '\\'; + temppath = ll_convert(std::filesystem::temp_directory_path().native()); + char sep = '\\'; #else - char sep = '/'; + temppath = std::filesystem::temp_directory_path().string(); + char sep = '/'; #endif - if (temppath[temppath.size() - 1] != sep) - { - temppath += sep; + if (temppath[temppath.size() - 1] != sep) + { + temppath += sep; + } } + return temppath; } -// static -std::filesystem::path LLFile::utf8StringToPath(const std::string& pathname) -{ #if LL_WINDOWS - return ll_convert(pathname); -#else - return pathname; -#endif -} -#if LL_WINDOWS +/************** input file stream ********************************/ -// static -std::wstring LLFile::utf8StringToWstring(const std::string& pathname) +// explicit +llifstream::llifstream(const char* _Filename, ios_base::openmode _Mode) : + std::ifstream(ll_convert(_Filename).c_str(), _Mode | ios_base::in) { - std::wstring utf16string(ll_convert(pathname)); - if (utf16string.size() >= MAX_PATH) - { - // By going through std::filesystem::path we get a lot of path sanitation done for us that - // is needed when passing a path with a kernel object space prefix to Windows API functions - // since this prefix disables the kernel32 path normalization - std::filesystem::path utf16path(utf16string); - - // By prepending "\\?\" to a path, Windows widechar file APIs will not fail on long path names - utf16string.assign(L"\\\\?\\").append(utf16path); - - /* remove trailing spaces and dots (yes, Windows really does that) */ - size_t last_valid = utf16string.find_last_not_of(L" \t."); - if (last_valid == std::wstring::npos) - { - return std::wstring(); - } - return utf16string.substr(0, last_valid + 1); - } - return utf16string; } -/************** input file stream ********************************/ - -llifstream::llifstream() {} - // explicit llifstream::llifstream(const std::string& _Filename, ios_base::openmode _Mode): std::ifstream(ll_convert( _Filename ).c_str(), @@ -1192,15 +1077,37 @@ llifstream::llifstream(const std::string& _Filename, ios_base::openmode _Mode): { } +// explicit +llifstream::llifstream(const std::filesystem::path& _Filepath, ios_base::openmode _Mode) : + std::ifstream(_Filepath, _Mode | ios_base::in) +{ +} + +void llifstream::open(const char* _Filename, ios_base::openmode _Mode) +{ + std::ifstream::open(ll_convert(_Filename).c_str(), + _Mode | ios_base::in); +} + void llifstream::open(const std::string& _Filename, ios_base::openmode _Mode) { std::ifstream::open(ll_convert(_Filename).c_str(), _Mode | ios_base::in); } +void llifstream::open(const std::filesystem::path& _Filepath, ios_base::openmode _Mode) +{ + std::ifstream::open(_Filepath, + _Mode | ios_base::in); +} + /************** output file stream ********************************/ -llofstream::llofstream() {} +// explicit +llofstream::llofstream(const char* _Filename, ios_base::openmode _Mode) : + std::ofstream(ll_convert(_Filename).c_str(), _Mode | ios_base::out) +{ +} // explicit llofstream::llofstream(const std::string& _Filename, ios_base::openmode _Mode): @@ -1209,10 +1116,27 @@ llofstream::llofstream(const std::string& _Filename, ios_base::openmode _Mode): { } +// explicit +llofstream::llofstream(const std::filesystem::path& _Filepath, ios_base::openmode _Mode) : + std::ofstream(_Filepath, _Mode | ios_base::out) +{ +} + +void llofstream::open(const char* _Filename, ios_base::openmode _Mode) +{ + std::ofstream::open(ll_convert(_Filename).c_str(), _Mode | ios_base::out); +} + void llofstream::open(const std::string& _Filename, ios_base::openmode _Mode) { std::ofstream::open(ll_convert( _Filename ).c_str(), _Mode | ios_base::out); } +void llofstream::open(const std::filesystem::path& _Filepath, ios_base::openmode _Mode) +{ + std::ofstream::open(_Filepath, + _Mode | ios_base::out); +} + #endif // LL_WINDOWS diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index dcd561ce7f..7e8e114098 100755 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -35,6 +35,8 @@ * Attempts to mostly mirror the POSIX style IO functions. */ +#include "stdtypes.h" + #include #include #include @@ -51,15 +53,24 @@ typedef struct stat llstat; typedef FILE LLFILE; +#include "fsyspath.h" #include "llstring.h" // safe char* -> std::string conversion +#ifndef TEXT +#if LL_WINDOWS +#define TEXT(flags) L##flags +#else +#define TEXT(flags) flags +#endif +#endif + /// This class provides a selection of functions to operate on files through names and /// a class implementation to represent a file for reading and writing to it /// All the functions with a path string input take UTF8 path/filenames /// /// @nosubgrouping /// -class LL_COMMON_API LLFile +class LLFile { public: // ================================================================================ @@ -157,12 +168,24 @@ public: } /// constructor opening the file - LLFile(const std::string& filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666) : + explicit LLFile(const char* filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666) : + mHandle(InvalidHandle) + { + open(filename, omode, ec, perm); + } + + explicit LLFile(const std::string& filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666) : mHandle(InvalidHandle) { open(filename, omode, ec, perm); } + explicit LLFile(const std::filesystem::path& file_path, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666) : + mHandle(InvalidHandle) + { + open(file_path, omode, ec, perm); + } + /// destructor always attempts to close the file ~LLFile() { close(); } ///@} @@ -198,7 +221,17 @@ public: ///@{ /// Open a file with the specific open mode flags - int open(const std::string& filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666); + inline int open(const char* filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666) + { + std::filesystem::path file_path = fsyspath(filename); + return open(file_path, omode, ec, perm); + } + inline int open(const std::string& filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666) + { + std::filesystem::path file_path = fsyspath(filename); + return open(file_path, omode, ec, perm); + } + int open(const std::filesystem::path& filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666); ///< @returns 0 on success, -1 on failure /// Determine the size of the opened file @@ -257,7 +290,23 @@ public: /// ///@{ /// open a file with the specified access mode - static LLFILE* fopen(const std::string& filename, const char* accessmode, int lmode = 0); + /// +#if LL_WINDOWS + using fopen_flags_t = wchar_t; +#else + using fopen_flags_t = char; +#endif + inline static LLFILE* fopen(const char* filename, const fopen_flags_t* accessmode, int lmode = 0) + { + std::filesystem::path file_path = fsyspath(filename); + return LLFile::fopen(file_path, accessmode, lmode); + } + inline static LLFILE* fopen(const std::string& filename, const fopen_flags_t* accessmode, int lmode = 0) + { + std::filesystem::path file_path = fsyspath(filename); + return LLFile::fopen(file_path, accessmode, lmode); + } + static LLFILE* fopen(const std::filesystem::path& file_path, const fopen_flags_t* accessmode, int lmode = 0); ///< 'accessmode' follows the rules of the Posix fopen() mode parameter /// "r" open the file for reading only and positions the stream at the beginning /// "r+" open the file for reading and writing and positions the stream at the beginning @@ -291,19 +340,63 @@ public: ///< @returns 0 on success and -1 on failure. /// create a directory - static int mkdir(const std::string& filename); + inline static int mkdir(const char* dirname) + { + std::filesystem::path dir_path = fsyspath(dirname); + return mkdir(dir_path); + } + inline static int mkdir(const std::string& dirname) + { + std::filesystem::path dir_path = fsyspath(dirname); + return mkdir(dir_path); + } + static int mkdir(const std::filesystem::path& dirname); ///< mkdir() considers "directory already exists" to be not an error. /// @returns 0 on success and -1 on failure. /// remove a file or directory - static int remove(const std::string& filename, int suppress_warning = 0); + inline static int remove(const char* filename, int suppress_warning = 0) + { + std::filesystem::path file_path = fsyspath(filename); + return remove(file_path, suppress_warning); + } + inline static int remove(const std::string& filename, int suppress_warning = 0) + { + std::filesystem::path file_path = fsyspath(filename); + return remove(file_path, suppress_warning); + } + static int remove(const std::filesystem::path& file_path, int suppress_warning = 0); ///< pass an errno value (e.g., ENOENT) in the optional 'suppress_warning' parameter if you want to /// suppress a warning in the log when the failure matches that errno (e.g., suppress warning if /// the file or directory does not exist) /// @returns 0 on success and -1 on failure. /// rename a file - static int rename(const std::string& filename, const std::string& newname, int suppress_warning = 0); + inline static int rename(const char* filename, const char* newname, int suppress_warning = 0) + { + std::filesystem::path file_path = fsyspath(filename); + std::filesystem::path new_path = fsyspath(newname); + return rename(file_path, new_path, suppress_warning); + } + inline static int rename(const std::string& filename, const char* newname, int suppress_warning = 0) + { + std::filesystem::path file_path = fsyspath(filename); + std::filesystem::path new_path = fsyspath(newname); + return rename(file_path, new_path, suppress_warning); + } + inline static int rename(const char* filename, const std::string& newname, int suppress_warning = 0) + { + std::filesystem::path file_path = fsyspath(filename); + std::filesystem::path new_path = fsyspath(newname); + return rename(file_path, new_path, suppress_warning); + } + inline static int rename(const std::string& filename, const std::string& newname, int suppress_warning = 0) + { + std::filesystem::path file_path = fsyspath(filename); + std::filesystem::path new_path = fsyspath(newname); + return rename(file_path, new_path, suppress_warning); + } + static int rename(const std::filesystem::path& file_path, const std::filesystem::path& new_path, int suppress_warning = 0); ///< it will silently overwrite newname if it exists without returning an error /// Posix guarantees that if newname already exists, then there will be no moment /// in which for other processes newname does not exist. There is no such guarantee @@ -312,7 +405,31 @@ public: /// @returns 0 on success and -1 on failure. /// copy the contents of the file from 'source' to 'target' - static bool copy(const std::string& source, const std::string& target); + inline static bool copy(const char* source, const char* target) + { + std::error_code ec; + return copy(source, target, std::filesystem::copy_options::overwrite_existing, ec); + } + inline static bool copy(const char* source, const std::string& target) + { + std::error_code ec; + return copy(source, target, std::filesystem::copy_options::overwrite_existing, ec); + } + inline static bool copy(const std::string& source, char* target) + { + std::error_code ec; + return copy(source, target, std::filesystem::copy_options::overwrite_existing, ec); + } + inline static bool copy(const std::string& source, const std::string& target) + { + std::error_code ec; + return copy(source, target, std::filesystem::copy_options::overwrite_existing, ec); + } + inline static bool copy(const std::filesystem::path& source_path, const std::filesystem::path& target_path) + { + std::error_code ec; + return copy(source_path, target_path, std::filesystem::copy_options::overwrite_existing, ec); + } ///< Copies the contents of the file 'source' to the file 'target', overwriting 'target' if it already /// existed. /// This is a convenience function that implements the previous behavior of silently overwriting an @@ -321,7 +438,31 @@ public: /// @returns true on success and false on failure. /// copy the contents of the file from 'from' to 'to' - static bool copy(const std::string& source, const std::string& target, std::filesystem::copy_options options, std::error_code& ec); + inline static bool copy(const char* source, const char* target, std::filesystem::copy_options options, std::error_code& ec) + { + std::filesystem::path source_path = fsyspath(source); + std::filesystem::path target_path = fsyspath(target); + return copy(source_path, target_path, options, ec); + } + inline static bool copy(const char* source, const std::string& target, std::filesystem::copy_options options, std::error_code& ec) + { + std::filesystem::path source_path = fsyspath(source); + std::filesystem::path target_path = fsyspath(target); + return copy(source_path, target_path, options, ec); + } + inline static bool copy(const std::string& source, const char* target, std::filesystem::copy_options options, std::error_code& ec) + { + std::filesystem::path source_path = fsyspath(source); + std::filesystem::path target_path = fsyspath(target); + return copy(source_path, target_path, options, ec); + } + inline static bool copy(const std::string& source, const std::string& target, std::filesystem::copy_options options, std::error_code& ec) + { + std::filesystem::path source_path = fsyspath(source); + std::filesystem::path target_path = fsyspath(target); + return copy(source_path, target_path, options, ec); + } + static bool copy(const std::filesystem::path& source_path, const std::filesystem::path& target_path, std::filesystem::copy_options options, std::error_code& ec); ///< Copies the contents of the file 'source' to the file 'target'. The options parameter allows to /// specify what should happen if the "target" file already exists: /// std::filesystem::copy_options::none - return an error in ec and fail @@ -331,48 +472,115 @@ public: /// @returns true on success and false on failure. /// retrieve the content of a file into a string - static std::string getContents(const std::string& filename); - static std::string getContents(const std::string& filename, std::error_code& ec); + inline static std::string getContents(const char* filename) + { + std::error_code ec; + return getContents(filename, ec); + } + inline static std::string getContents(const std::string& filename) + { + std::error_code ec; + return getContents(filename, ec); + } + inline static std::string getContents(const std::filesystem::path& file_path) + { + std::error_code ec; + return getContents(file_path, ec); + } + inline static std::string getContents(const char* filename, std::error_code& ec) + { + std::filesystem::path file_path = fsyspath(filename); + return getContents(file_path, ec); + } + inline static std::string getContents(const std::string& filename, std::error_code& ec) + { + std::filesystem::path file_path = fsyspath(filename); + return getContents(file_path, ec); + } + static std::string getContents(const std::filesystem::path& file_path, std::error_code& ec); ///< @returns the entire content of the file as std::string or an empty string on failure /// read nBytes from the file into the buffer, starting at offset in the file - static S64 read(const std::string& filename, void* buf, S64 offset, S64 nbytes); - static S64 read(const std::string& filename, void* buf, S64 offset, S64 nbytes, std::error_code& ec); + inline static S64 read(const char* filename, void* buf, S64 offset, S64 nbytes) + { + std::error_code ec; + return read(filename, buf, offset, nbytes, ec); + } + inline static S64 read(const std::string& filename, void* buf, S64 offset, S64 nbytes) + { + std::error_code ec; + return read(filename, buf, offset, nbytes, ec); + } + inline static S64 read(const std::filesystem::path& file_path, void* buf, S64 offset, S64 nbytes) + { + std::error_code ec; + return read(file_path, buf, offset, nbytes, ec); + } + inline static S64 read(const char* filename, void* buf, S64 offset, S64 nbytes, std::error_code& ec) + { + std::filesystem::path file_path = fsyspath(filename); + return read(file_path, buf, offset, nbytes, ec); + } + inline static S64 read(const std::string& filename, void* buf, S64 offset, S64 nbytes, std::error_code& ec) + { + std::filesystem::path file_path = fsyspath(filename); + return read(file_path, buf, offset, nbytes, ec); + } + static S64 read(const std::filesystem::path& filename, void* buf, S64 offset, S64 nbytes, std::error_code& ec); ///< @returns bytes read on success, or -1 on failure /// write nBytes from the buffer into the file, starting at offset in the file - static S64 write(const std::string& filename, const void* buf, S64 offset, S64 nbytes); - static S64 write(const std::string& filename, const void* buf, S64 offset, S64 nbytes, std::error_code& ec); + inline static S64 write(const std::string& filename, const void* buf, S64 offset, S64 nbytes) + { + std::error_code ec; + std::filesystem::path file_path = fsyspath(filename); + return write(file_path, buf, offset, nbytes, ec); + } + inline static S64 write(const std::filesystem::path& filename, const void* buf, S64 offset, S64 nbytes) + { + std::error_code ec; + std::filesystem::path file_path = fsyspath(filename); + return write(file_path, buf, offset, nbytes, ec); + } + inline static S64 write(const std::string& filename, const void* buf, S64 offset, S64 nbytes, std::error_code& ec) + { + std::filesystem::path file_path = fsyspath(filename); + return write(file_path, buf, offset, nbytes, ec); + } + static S64 write(const std::filesystem::path& filename, const void* buf, S64 offset, S64 nbytes, std::error_code& ec); ///< If a negative offset is provided, the file is opened in append mode and the /// write will be appended to the end of the file. /// @returns bytes written on success, or -1 on failure /// return the file stat structure for filename - static int stat(const std::string& filename, llstat* file_status, const char *operation = nullptr, int suppress_warning = ENOENT); + inline static int stat(const char* filename, llstat* file_status, const char* operation = nullptr, int suppress_warning = ENOENT) + { + std::filesystem::path file_path = fsyspath(filename); + return stat(file_path, file_status, operation, suppress_warning); + } + inline static int stat(const std::string& filename, llstat* file_status, const char* operation = nullptr, int suppress_warning = ENOENT) + { + std::filesystem::path file_path = fsyspath(filename); + return stat(file_path, file_status, operation, suppress_warning); + } + static int stat(const std::filesystem::path& file_path, llstat* file_status, const char *operation = nullptr, int suppress_warning = ENOENT); ///< for compatibility with existing uses of LL_File::stat() we use ENOENT as default in the /// optional 'suppress_warning' parameter to avoid spamming the log with warnings when the API /// is used to detect if a file exists /// @returns 0 on success and -1 on failure. - /// get the creation data and time of a file - static std::time_t getCreationTime(const std::string& filename, int suppress_warning = 0); - ///< Different systems have different support for this. Under Windows this is supposedly - /// the actual time the file was created, on the Mac this is the actual birth date of - /// the file which is in fact the creation time. The according ctime entry in the stat - /// structure under Linux (and any other *nix really) is however contrary to what one - /// might expect based on the c in ctime not the creation time but the time the last - /// change to the inode entry was made. Changing access rights to a file will update - /// this value too. In order to have a true creation time under Linux, we would have - /// to use the statx() call which is available since kernel 4.19, but that will require - /// considerable changes to the implementation of above stat() function. - /// @returns the creation time (last status change under Linux) of the file or 0 on error - - /// get the last modification data and time of a file - static std::time_t getModificationTime(const std::string& filename, int suppress_warning = 0); - ///< @returns the modification time of the file or 0 on error - /// get the std::filesystem::file_status for filename - static std::filesystem::file_status getStatus(const std::string& filename, bool dontFollowSymLink = false, int suppress_warning = ENOENT); + inline static std::filesystem::file_status getStatus(const char* filename, bool dontFollowSymLink = false, int suppress_warning = ENOENT) + { + std::filesystem::path file_path = fsyspath(filename); + return getStatus(file_path, dontFollowSymLink, suppress_warning); + } + inline static std::filesystem::file_status getStatus(const std::string& filename, bool dontFollowSymLink = false, int suppress_warning = ENOENT) + { + std::filesystem::path file_path = fsyspath(filename); + return getStatus(file_path, dontFollowSymLink, suppress_warning); + } + static std::filesystem::file_status getStatus(const std::filesystem::path& file_path, bool dontFollowSymLink = false, int suppress_warning = ENOENT); ///< dontFollowSymLinks set to true returns the std::filesystem::file_status of the symlink if it /// is one, rather than resolving it. We pass by default ENOENT in the optional 'suppress_warning' /// parameter to not spam the log with warnings when the file or directory does not exist @@ -380,66 +588,108 @@ public: /// and other APIs accepting a file_status. /// get the size of a file in bytes - static S64 size(const std::string& filename, int suppress_warning = ENOENT); + inline static S64 size(const char* filename, int suppress_warning = ENOENT) + { + std::filesystem::path file_path = fsyspath(filename); + return size(file_path, suppress_warning); + } + inline static S64 size(const std::string& filename, int suppress_warning = ENOENT) + { + std::filesystem::path file_path = fsyspath(filename); + return size(file_path, suppress_warning); + } + static S64 size(const std::filesystem::path& file_path, int suppress_warning = ENOENT); ///< we pass by default ENOENT in the optional 'suppress_warning' parameter to not spam /// the log with warnings when the file does not exist /// @returns the file size on success or 0 on failure. /// check if filename is an existing file or directory - static bool exists(const std::string& filename); + inline static bool exists(const char* filename) + { + std::filesystem::file_status status = getStatus(filename); + return std::filesystem::exists(status); + } + inline static bool exists(const std::string& filename) + { + std::filesystem::file_status status = getStatus(filename); + return std::filesystem::exists(status); + } + inline static bool exists(const std::filesystem::path& file_path) + { + std::filesystem::file_status status = getStatus(file_path); + return std::filesystem::exists(status); + } ///< @returns true if the path is for an existing file or directory /// check if filename is an existing directory - static bool isdir(const std::string& filename); + inline static bool isdir(const char* filename) + { + std::filesystem::file_status status = getStatus(filename); + return std::filesystem::is_directory(status); + } + inline static bool isdir(const std::string& filename) + { + std::filesystem::file_status status = getStatus(filename); + return std::filesystem::is_directory(status); + } + inline static bool isdir(const std::filesystem::path& file_path) + { + std::filesystem::file_status status = getStatus(file_path); + return std::filesystem::is_directory(status); + } ///< @returns true if the path is for an existing directory /// check if filename is an existing file - static bool isfile(const std::string& filename); + inline static bool isfile(const char* filename) + { + std::filesystem::file_status status = getStatus(filename); + return std::filesystem::is_regular_file(status); + } + inline static bool isfile(const std::string& filename) + { + std::filesystem::file_status status = getStatus(filename); + return std::filesystem::is_regular_file(status); + } + inline static bool isfile(const std::filesystem::path& file_path) + { + std::filesystem::file_status status = getStatus(file_path); + return std::filesystem::is_regular_file(status); + } ///< @returns true if the path is for an existing file /// check if filename is a symlink - static bool islink(const std::string& filename); + inline static bool islink(const char* filename) + { + std::filesystem::file_status status = getStatus(filename, true); + return std::filesystem::is_symlink(status); + } + inline static bool islink(const std::string& filename) + { + std::filesystem::file_status status = getStatus(filename, true); + return std::filesystem::is_symlink(status); + } + inline static bool islink(const std::filesystem::path& file_path) + { + std::filesystem::file_status status = getStatus(file_path, true); + return std::filesystem::is_symlink(status); + } ///< @returns true if the path is pointing at a symlink /// return a path to the temporary directory on the system static const std::string& tmpdir(); - /// converts a string containing a path in utf8 encoding into an explicit filesystem path - static std::filesystem::path utf8StringToPath(const std::string& pathname); - ///< @returns the path as a std::filesystem::path - ///@} - private: #if LL_WINDOWS typedef HANDLE llfile_handle_t; const llfile_handle_t InvalidHandle = INVALID_HANDLE_VALUE; + llfile_handle_t mHandle = INVALID_HANDLE_VALUE; // The file handle/descriptor #else typedef int llfile_handle_t; const llfile_handle_t InvalidHandle = -1; + llfile_handle_t mHandle = -1;; // The file handle/descriptor #endif - /// ================================================================================ - /// @name private static member functions - /// -#if LL_WINDOWS - /// convert a string containing a path in utf8 encoding into a Windows format std::wstring - static std::wstring utf8StringToWstring(const std::string& pathname); - ///< this will prepend the path with the Windows kernel object space prefix when the path is - /// equal or longer than MAX_PATH characters and do some sanitation on the path. - /// This allows the underlaying Windows APIs to process long path names. Do not pass such a path - /// to std::filesystem functions. These functions are not guaranteed to handle such paths properly. - /// It's only useful to pass the resulting string buffer to Microsoft Windows widechar APIs or - /// the Microsoft C runtime widechar file functions. - /// - /// Example: - /// - /// std::wstring file_path = utf8StringToWstring(filename); - /// HANDLE CreateFileW(file_path.c_str(), ......); - /// - /// @returns the path as a std::wstring path -#endif - llfile_handle_t mHandle; // The file handle/descriptor - std::ios_base::openmode mOpen; // Used to emulate std::ios_base::app under Windows + std::ios_base::openmode mOpen{}; // Used to emulate std::ios_base::app under Windows }; #if LL_WINDOWS @@ -451,7 +701,7 @@ private: * Does The Right Thing when passed a non-ASCII pathname. Sadly, that isn't * true of Microsoft's std::ifstream. */ -class LL_COMMON_API llifstream : public std::ifstream +class llifstream : public std::ifstream { // input stream associated with a C stream public: @@ -463,7 +713,7 @@ class LL_COMMON_API llifstream : public std::ifstream * @c &sb to the base class initializer. Does not open any files * (you haven't given it a filename to open). */ - llifstream(); + llifstream() = default; /** * @brief Create an input file stream. @@ -472,8 +722,12 @@ class LL_COMMON_API llifstream : public std::ifstream * * @c ios_base::in is automatically included in @a mode. */ + explicit llifstream(const char* _Filename, + ios_base::openmode _Mode = ios_base::in); explicit llifstream(const std::string& _Filename, ios_base::openmode _Mode = ios_base::in); + explicit llifstream(const std::filesystem::path& _Filepath, + ios_base::openmode _Mode = ios_base::in); /** * @brief Opens an external file. @@ -483,10 +737,73 @@ class LL_COMMON_API llifstream : public std::ifstream * Calls @c llstdio_filebuf::open(s,mode|in). If that function * fails, @c failbit is set in the stream's error state. */ + void open(const char* _Filename, + ios_base::openmode _Mode = ios_base::in); void open(const std::string& _Filename, ios_base::openmode _Mode = ios_base::in); + void open(const std::filesystem::path& _Filepath, + ios_base::openmode _Mode = ios_base::in); }; +/// RAII class +class LLUniqueFile +{ +public: + // empty + LLUniqueFile() = default; + // wrap (e.g.) result of LLFile::fopen() + LLUniqueFile(LLFILE* f) : mFileHandle(f) {} + // no copy + LLUniqueFile(const LLUniqueFile&) = delete; + // move construction + LLUniqueFile(LLUniqueFile&& other) noexcept + { + mFileHandle = other.mFileHandle; + other.mFileHandle = nullptr; + } + // The point of LLUniqueFile is to close on destruction. + ~LLUniqueFile() { close(); } + + // simple assignment + LLUniqueFile& operator=(LLFILE* f) + { + close(); + mFileHandle = f; + return *this; + } + // copy assignment deleted + LLUniqueFile& operator=(const LLUniqueFile&) = delete; + // move assignment + LLUniqueFile& operator=(LLUniqueFile&& other) noexcept + { + close(); + std::swap(mFileHandle, other.mFileHandle); + return *this; + } + + // explicit close operation + void close() + { + if (mFileHandle) + { + // in case close() throws, set mFileHandle null FIRST + LLFILE* h{ nullptr }; + std::swap(h, mFileHandle); + LLFile::close(h); + } + } + + // detect whether the wrapped LLFILE is open or not + explicit operator bool() const { return bool(mFileHandle); } + bool operator!() { return !mFileHandle; } + + // LLUniqueFile should be usable for any operation that accepts LLFILE* + // (or FILE* for that matter) + operator LLFILE*() const { return mFileHandle; } + +private: + LLFILE* mFileHandle = nullptr; +}; /** * @brief Controlling output for files. @@ -496,7 +813,7 @@ class LL_COMMON_API llifstream : public std::ifstream * Right Thing when passed a non-ASCII pathname. Sadly, that isn't true of * Microsoft's std::ofstream. */ -class LL_COMMON_API llofstream : public std::ofstream +class llofstream : public std::ofstream { public: // Constructors: @@ -507,7 +824,7 @@ class LL_COMMON_API llofstream : public std::ofstream * @c &sb to the base class initializer. Does not open any files * (you haven't given it a filename to open). */ - llofstream(); + llofstream() = default; /** * @brief Create an output file stream. @@ -516,8 +833,12 @@ class LL_COMMON_API llofstream : public std::ofstream * * @c ios_base::out is automatically included in @a mode. */ + explicit llofstream(const char* _Filename, + ios_base::openmode _Mode = ios_base::out|ios_base::trunc); explicit llofstream(const std::string& _Filename, ios_base::openmode _Mode = ios_base::out|ios_base::trunc); + explicit llofstream(const std::filesystem::path& _Filepath, + ios_base::openmode _Mode = ios_base::out|ios_base::trunc); /** * @brief Opens an external file. @@ -526,8 +847,12 @@ class LL_COMMON_API llofstream : public std::ofstream * * @c ios_base::out is automatically included in @a mode. */ + void open(const char* _Filename, + ios_base::openmode _Mode = ios_base::out|ios_base::trunc); void open(const std::string& _Filename, ios_base::openmode _Mode = ios_base::out|ios_base::trunc); + void open(const std::filesystem::path& _Filepath, + ios_base::openmode _Mode = ios_base::out|ios_base::trunc); }; #else // ! LL_WINDOWS diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 37d1c60f91..7656986fe2 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -837,7 +837,7 @@ private: void get_proc_cpuinfo() { std::map< std::string, std::string > cpuinfo; - LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); + LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, TEXT("rb")); if(cpuinfo_fp) { char line[MAX_STRING]; @@ -954,7 +954,7 @@ private: std::ostringstream s; // *NOTE:Mani - This is for linux only. - LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); + LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, TEXT("rb")); if(cpuinfo) { char line[MAX_STRING]; diff --git a/indra/llcommon/llprofilercategories.h b/indra/llcommon/llprofilercategories.h index 1c4f0f5624..261fdf14b7 100644 --- a/indra/llcommon/llprofilercategories.h +++ b/indra/llcommon/llprofilercategories.h @@ -48,6 +48,7 @@ #define LL_PROFILER_CATEGORY_ENABLE_DRAWPOOL 1 #define LL_PROFILER_CATEGORY_ENABLE_ENVIRONMENT 1 #define LL_PROFILER_CATEGORY_ENABLE_FACE 1 +//#define LL_PROFILER_CATEGORY_ENABLE_FILE 1 #define LL_PROFILER_CATEGORY_ENABLE_LLSD 1 #define LL_PROFILER_CATEGORY_ENABLE_LOGGING 1 #define LL_PROFILER_CATEGORY_ENABLE_MATERIAL 1 @@ -126,6 +127,14 @@ #define LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE #endif +#if LL_PROFILER_CATEGORY_ENABLE_FILE +#define LL_PROFILE_ZONE_NAMED_CATEGORY_FILE LL_PROFILE_ZONE_NAMED +#define LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE LL_PROFILE_ZONE_SCOPED +#else +#define LL_PROFILE_ZONE_NAMED_CATEGORY_FILE(name) +#define LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE +#endif + #if LL_PROFILER_CATEGORY_ENABLE_LLSD #define LL_PROFILE_ZONE_NAMED_CATEGORY_LLSD LL_PROFILE_ZONE_NAMED #define LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD LL_PROFILE_ZONE_SCOPED diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 9b5dd2df39..499de996e2 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -514,7 +514,7 @@ namespace { #if LL_LINUX constexpr U32 STATUS_SIZE = 2048; - LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); + LLFILE* status_filep = LLFile::fopen("/proc/self/status", TEXT("rb")); if (status_filep) { char buff[STATUS_SIZE]; /* Flawfinder: ignore */ @@ -1273,7 +1273,7 @@ bool gunzip_file(const std::string& srcfile, const std::string& dstfile) src = gzopen(srcfile.c_str(), "rb"); #endif if (! src) goto err; - dst = LLFile::fopen(tmpfile, "wb"); /* Flawfinder: ignore */ + dst = LLFile::fopen(tmpfile, TEXT("wb")); /* Flawfinder: ignore */ if (! dst) goto err; do { @@ -1314,7 +1314,7 @@ bool gzip_file(const std::string& srcfile, const std::string& dstfile) #endif if (! dst) goto err; - src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */ + src = LLFile::fopen(srcfile, TEXT("rb")); /* Flawfinder: ignore */ if (! src) goto err; while ((bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE, src)) > 0) diff --git a/indra/llcommon/tests/llfile_test.cpp b/indra/llcommon/tests/llfile_test.cpp index f1cee06856..ab4616cfb2 100644 --- a/indra/llcommon/tests/llfile_test.cpp +++ b/indra/llcommon/tests/llfile_test.cpp @@ -33,14 +33,13 @@ namespace tut { - static void clear_entire_dir(const std::string &dir) + static void clear_entire_dir(const std::filesystem::path& dir_path) { std::error_code ec; - std::filesystem::path dir_path = LLFile::utf8StringToPath(dir); std::filesystem::remove_all(dir_path, ec); } - static std::filesystem::path append_filename(const std::filesystem::path& dir, const std::string& element) + static std::filesystem::path append_filename(const std::filesystem::path& dir, const std::u8string& element) { std::filesystem::path path = dir; return path.append(element); @@ -48,13 +47,13 @@ namespace tut static std::filesystem::path get_testdir(const std::filesystem::path& tempdir) { - return append_filename(tempdir, std::string("test_dir")); + return append_filename(tempdir, std::u8string(u8"test_dir")); } static std::filesystem::path get_testdir_unicode(const std::filesystem::path& tempdir) { // Example Unicode directory name: "test_ユニコード_dir" - return append_filename(tempdir, std::string("test_\xE3\x83\xA6\xE3\x83\x8B\xE3\x82\xB3\xE3\x83\xBC\xE3\x83\x89_dir")); + return append_filename(tempdir, std::u8string(u8"test_\xE3\x83\xA6\xE3\x83\x8B\xE3\x82\xB3\xE3\x83\xBC\xE3\x83\x89_dir")); } struct llfile_test @@ -72,46 +71,46 @@ namespace tut // Test creating directories and files and deleting them and checking if the // relevant status functions work as expected ensure("LLFile::tmpdir() empty", !tempdir.empty()); - ensure("LLFile::tmpdir() doesn't exist", LLFile::exists(tempdir.string())); - ensure("LLFile::tmpdir() is not a directory", LLFile::isdir(tempdir.string())); - ensure("LLFile::tmpdir() should not be a file", !LLFile::isfile(tempdir.string())); + ensure("LLFile::tmpdir() doesn't exist", LLFile::exists(tempdir)); + ensure("LLFile::tmpdir() is not a directory", LLFile::isdir(tempdir)); + ensure("LLFile::tmpdir() should not be a file", !LLFile::isfile(tempdir)); // Make sure there is nothing left from a previous test run - clear_entire_dir(testdir.string()); - ensure("llfile_test should not exist anymore", !LLFile::exists(testdir.string())); + clear_entire_dir(testdir); + ensure("llfile_test should not exist anymore", !LLFile::exists(testdir)); - int rc = LLFile::mkdir(testdir.string()); + int rc = LLFile::mkdir(testdir); ensure("LLFile::mkdir() failed", rc == 0); - ensure("llfile_test should be a directory", LLFile::isdir(testdir.string())); - rc = LLFile::mkdir(testdir.string()); + ensure("llfile_test should be a directory", LLFile::isdir(testdir)); + rc = LLFile::mkdir(testdir); ensure("LLFile::mkdir() should not fail when the directory already exists", rc == 0); std::filesystem::path testfile1 = testdir; testfile1.append("llfile_test.dat"); - ensure("llfile_test1.dat should not yet exist", !LLFile::exists(testfile1.string())); + ensure("llfile_test1.dat should not yet exist", !LLFile::exists(testfile1)); const char* testdata = "testdata"; - S64 bytes = LLFile::write(testfile1.string(), testdata, 0, sizeof(testdata)); + S64 bytes = LLFile::write(testfile1, testdata, 0, sizeof(testdata)); ensure("LLFile::write() did not write correctly", bytes == sizeof(testdata)); - rc = LLFile::remove(testfile1.string()); + rc = LLFile::remove(testfile1); ensure("LLFile::remove() for file test_file.dat", rc == 0); - ensure("llfile_test.dat should not exist anymore", !LLFile::exists(testfile1.string())); - ensure("llfile_test.dat should not be a file", !LLFile::isfile(testfile1.string())); - ensure("llfile_test.dat should not be a directory", !LLFile::isdir(testfile1.string())); - ensure("llfile_test.dat should not be a symlink", !LLFile::islink(testfile1.string())); + ensure("llfile_test.dat should not exist anymore", !LLFile::exists(testfile1)); + ensure("llfile_test.dat should not be a file", !LLFile::isfile(testfile1)); + ensure("llfile_test.dat should not be a directory", !LLFile::isdir(testfile1)); + ensure("llfile_test.dat should not be a symlink", !LLFile::islink(testfile1)); - rc = LLFile::remove(testdir.string()); + rc = LLFile::remove(testdir); ensure("LLFile::remove() for directory llfile_test failed", rc == 0); - ensure("llfile_test should not exist anymore", !LLFile::exists(testdir.string())); + ensure("llfile_test should not exist anymore", !LLFile::exists(testdir)); } template<> template<> void llfile_test_object_t::test<2>() { // High level static file IO functions to read and write data files - LLFile::mkdir(testdir.string()); - ensure("llfile_test should exist", LLFile::isdir(testdir.string())); + LLFile::mkdir(testdir); + ensure("llfile_test should exist", LLFile::isdir(testdir)); std::filesystem::path testfile1 = testdir; testfile1.append("llfile_test.dat"); @@ -119,42 +118,36 @@ namespace tut std::string testdata1("testdata"); std::string testdata2("datateststuff"); std::time_t current = time(nullptr); - S64 bytes = LLFile::write(testfile1.string(), testdata1.c_str(), 0, testdata1.length()); + S64 bytes = LLFile::write(testfile1, testdata1.c_str(), 0, testdata1.length()); ensure("LLFile::write() did not write correctly", bytes == testdata1.length()); - ensure("llfile_test.dat should exist", LLFile::exists(testfile1.string())); - ensure("llfile_test.dat should be a file", LLFile::isfile(testfile1.string())); - ensure("llfile_test.dat should not be a directory", !LLFile::isdir(testfile1.string())); + ensure("llfile_test.dat should exist", LLFile::exists(testfile1)); + ensure("llfile_test.dat should be a file", LLFile::isfile(testfile1)); + ensure("llfile_test.dat should not be a directory", !LLFile::isdir(testfile1)); - bytes = LLFile::size(testfile1.string()); + bytes = LLFile::size(testfile1); ensure("LLFile::size() did not return the correct size", bytes == testdata1.length()); - std::string data = LLFile::getContents(testfile1.string()); + std::string data = LLFile::getContents(testfile1); ensure("LLFile::getContents() did not return the correct size data", data.length() == testdata1.length()); ensure_memory_matches("LLFile::getContents() did not read correct data", testdata1.c_str(), (U32)testdata1.length(), data.c_str(), (U32)data.length()); - std::time_t ctime = LLFile::getCreationTime(testfile1.string()); - ensure_approximately_equals_range("LLFile::getCreationTime() did not return correct time", (F32)(ctime - current), 0.f, 1); - - std::time_t mtime = LLFile::getModificationTime(testfile1.string()); - ensure_approximately_equals_range("LLFile::getModificationTime() did not return correct time", (F32)(mtime - current), 0.f, 1); - char buffer[1024]; - bytes = LLFile::read(testfile1.string(), buffer, 0, testdata1.length()); + bytes = LLFile::read(testfile1, buffer, 0, testdata1.length()); ensure("LLFile:read() did not return the correct size", bytes == testdata1.length()); ensure_memory_matches("LLFile::read() did not read correct data", testdata1.c_str(), (U32)bytes, buffer, (U32)bytes); // What if we try to read more data than there is in the file? - bytes = LLFile::read(testfile1.string(), buffer, 0, bytes + 10); + bytes = LLFile::read(testfile1, buffer, 0, bytes + 10); ensure("LLFile:read() did not correctly stop on eof", bytes == testdata1.length()); ensure_memory_matches("LLFile::read() did not read correct data", testdata1.c_str(), (U32)bytes, buffer, (U32)bytes); // Let's append more data - bytes = LLFile::write(testfile1.string(), testdata2.c_str(), -1, testdata2.length()); + bytes = LLFile::write(testfile1, testdata2.c_str(), -1, testdata2.length()); ensure("LLFile::write() did not write correctly", bytes == testdata2.length()); - bytes = LLFile::size(testfile1.string()); + bytes = LLFile::size(testfile1); ensure("LLFile::size() did not return the correct size", bytes == testdata1.length() + testdata2.length()); - bytes = LLFile::read(testfile1.string(), buffer, 0, bytes); + bytes = LLFile::read(testfile1, buffer, 0, bytes); ensure("LLFile:read() did not read correct number of bytes", bytes == testdata1.length() + testdata2.length()); ensure_memory_matches("LLFile:read() did not read correct testdata1", testdata1.c_str(), (U32)testdata1.length(), buffer, (U32)testdata1.length()); ensure_memory_matches("LLFile:read() did not read correct testdata2", testdata2.c_str(), (U32)testdata2.length(), buffer + testdata1.length(), (U32)testdata2.length()); @@ -176,7 +169,7 @@ namespace tut } std::error_code ec; - LLFile fileout(testfile.string(), LLFile::out, ec); + LLFile fileout(testfile, LLFile::out, ec); ensure("LLFile constructor did not open correctly", (bool)fileout); ensure("error_code from LLFile constructor should not indicate an error", !ec); if (fileout) @@ -196,7 +189,7 @@ namespace tut fileout.close(); } - LLFile filein(testfile.string(), LLFile::in, ec); + LLFile filein(testfile, LLFile::in, ec); ensure("LLFile constructor did not open correctly", (bool)filein); ensure("error_code from LLFile constructor should not indicate an error", !ec); if (filein) @@ -236,16 +229,16 @@ namespace tut testfile.append("llfile_test.bin"); std::error_code ec; - LLFile file(testfile.string(), LLFile::out | LLFile::noreplace, ec); + LLFile file(testfile, LLFile::out | LLFile::noreplace, ec); ensure("LLFile constructor should not have opened the already existing file", !file); ensure("error_code from LLFile constructor should indicate an error", (bool)ec); - LLFile::remove(testfile.string()); - file = LLFile(testfile.string(), LLFile::out | LLFile::app | LLFile::trunc, ec); + LLFile::remove(testfile); + file = LLFile(testfile, LLFile::out | LLFile::app | LLFile::trunc, ec); ensure("LLFile constructor should not have opened the file with conflicting flags", !file); ensure("error_code from LLFile constructor should indicate an error", (bool)ec); - file = LLFile(testfile.string(), LLFile::out | LLFile::app | LLFile::noreplace, ec); + file = LLFile(testfile, LLFile::out | LLFile::app | LLFile::noreplace, ec); ensure("LLFile constructor should not have opened the file with conflicting flags", !file); ensure("error_code from LLFile constructor should indicate an error", (bool)ec); @@ -253,7 +246,7 @@ namespace tut testfile.append("llfile_test"); testfile.append("llfile_test.bin"); - file = LLFile(testfile.string(), LLFile::in, ec); + file = LLFile(testfile, LLFile::in, ec); ensure("LLFile constructor should not have been able to open the file in the non-existing directory", !file); ensure("error_code from LLFile constructor should indicate an error", (bool)ec); } @@ -270,37 +263,37 @@ namespace tut testfile_unicode.append(unicode_filename); // Clean up any previous test artifacts - clear_entire_dir(testdir_unicode.string()); - ensure("Unicode test directory should not exist", !LLFile::exists(testdir_unicode.string())); + clear_entire_dir(testdir_unicode); + ensure("Unicode test directory should not exist", !LLFile::exists(testdir_unicode)); // Create the Unicode directory - int rc = LLFile::mkdir(testdir_unicode.string()); + int rc = LLFile::mkdir(testdir_unicode); ensure("LLFile::mkdir() failed for Unicode directory", rc == 0); - ensure("Unicode test directory should exist", LLFile::isdir(testdir_unicode.string())); + ensure("Unicode test directory should exist", LLFile::isdir(testdir_unicode)); - ensure("Unicode test file should not exist", !LLFile::exists(testfile_unicode.string())); + ensure("Unicode test file should not exist", !LLFile::exists(testfile_unicode)); // Write to the Unicode file const char* testdata = "unicode_testdata"; - S64 bytes = LLFile::write(testfile_unicode.string(), testdata, 0, strlen(testdata)); - ensure("Unicode test file should exist", LLFile::exists(testfile_unicode.string())); - ensure("Unicode test file should be a file", LLFile::isfile(testfile_unicode.string())); + S64 bytes = LLFile::write(testfile_unicode, testdata, 0, strlen(testdata)); + ensure("Unicode test file should exist", LLFile::exists(testfile_unicode)); + ensure("Unicode test file should be a file", LLFile::isfile(testfile_unicode)); ensure("LLFile::write() did not write correctly to Unicode file", bytes == (S64)strlen(testdata)); // Read back the data char buffer[64] = {}; - bytes = LLFile::read(testfile_unicode.string(), buffer, 0, sizeof(buffer)); + bytes = LLFile::read(testfile_unicode, buffer, 0, sizeof(buffer)); ensure("LLFile::read() did not read correctly from Unicode file", bytes == (S64)strlen(testdata)); ensure_memory_matches("LLFile::read() did not read correct Unicode data", testdata, (U32)bytes, buffer, (U32)bytes); // Remove the file and directory - rc = LLFile::remove(testfile_unicode.string()); + rc = LLFile::remove(testfile_unicode); ensure("LLFile::remove() failed for Unicode file", rc == 0); - ensure("Unicode test file should not exist after removal", !LLFile::exists(testfile_unicode.string())); + ensure("Unicode test file should not exist after removal", !LLFile::exists(testfile_unicode)); - rc = LLFile::remove(testdir_unicode.string()); + rc = LLFile::remove(testdir_unicode); ensure("LLFile::remove() failed for Unicode directory", rc == 0); - ensure("Unicode test directory should not exist after removal", !LLFile::exists(testdir_unicode.string())); + ensure("Unicode test directory should not exist after removal", !LLFile::exists(testdir_unicode)); } } // namespace tut diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp index eb3c2d9909..3ec8983e8a 100755 --- a/indra/llfilesystem/lldir.cpp +++ b/indra/llfilesystem/lldir.cpp @@ -91,13 +91,13 @@ LLDir::~LLDir() std::vector LLDir::getFilesInDir(const std::string &dirname) { // Returns a vector of filenames in the directory. - std::filesystem::path p = LLFile::utf8StringToPath(dirname); + fsyspath dir_path(dirname); std::vector v; std::error_code ec; - if (std::filesystem::is_directory(p, ec)) + if (std::filesystem::is_directory(dir_path, ec)) { std::filesystem::directory_iterator end_iter; - for (std::filesystem::directory_iterator dir_itr(p); + for (std::filesystem::directory_iterator dir_itr(dir_path); dir_itr != end_iter; ++dir_itr) { @@ -173,10 +173,10 @@ U32 LLDir::deleteDirAndContents(const std::string& dir_name) //Removes the directory and its contents. Returns number of files deleted. U32 num_deleted = 0; - std::filesystem::path dir_path = LLFile::utf8StringToPath(dir_name); try { + fsyspath dir_path(dir_name); if (std::filesystem::is_directory(dir_path)) { if (!std::filesystem::is_empty(dir_path)) @@ -196,6 +196,11 @@ U32 LLDir::deleteDirAndContents(const std::string& dir_name) return num_deleted; } +bool LLDir::fileExists(const std::string& filename) const +{ + return LLFile::exists(filename); +} + const std::string LLDir::findFile(const std::string &filename, const std::string& searchPath1, const std::string& searchPath2, @@ -1005,7 +1010,7 @@ bool LLDir::setCacheDir(const std::string &path) { LLFile::mkdir(path); std::string tempname = add(path, "temp"); - LLFILE* file = LLFile::fopen(tempname,"wt"); + LLFILE* file = LLFile::fopen(tempname, TEXT("wt")); if (file) { fclose(file); diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h index b0d2b6aada..8388816059 100644 --- a/indra/llfilesystem/lldir.h +++ b/indra/llfilesystem/lldir.h @@ -71,7 +71,7 @@ class LLDir std::vector getFilesInDir(const std::string &dirname); // pure virtual functions virtual std::string getCurPath() = 0; - virtual bool fileExists(const std::string &filename) const = 0; + virtual bool fileExists(const std::string &filename) const; const std::string findFile(const std::string& filename, const std::vector filenames) const; const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const; diff --git a/indra/llfilesystem/lldir_linux.cpp b/indra/llfilesystem/lldir_linux.cpp index b13b42c954..0ebaab1114 100644 --- a/indra/llfilesystem/lldir_linux.cpp +++ b/indra/llfilesystem/lldir_linux.cpp @@ -238,24 +238,6 @@ std::string LLDir_Linux::getCurPath() return tmp_str; } - -bool LLDir_Linux::fileExists(const std::string &filename) const -{ - struct stat stat_data; - // Check the age of the file - // Now, we see if the files we've gathered are recent... - int res = stat(filename.c_str(), &stat_data); - if (!res) - { - return true; - } - else - { - return false; - } -} - - /*virtual*/ std::string LLDir_Linux::getLLPluginLauncher() { return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + diff --git a/indra/llfilesystem/lldir_linux.h b/indra/llfilesystem/lldir_linux.h index bd031bd7bb..ad9cd76554 100644 --- a/indra/llfilesystem/lldir_linux.h +++ b/indra/llfilesystem/lldir_linux.h @@ -47,7 +47,6 @@ public: virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/llfilesystem/lldir_mac.cpp b/indra/llfilesystem/lldir_mac.cpp index 2db1b6ec5d..7bddee0f75 100644 --- a/indra/llfilesystem/lldir_mac.cpp +++ b/indra/llfilesystem/lldir_mac.cpp @@ -177,14 +177,6 @@ std::string LLDir_Mac::getCurPath() return boost::filesystem::path( boost::filesystem::current_path() ).string(); } - - -bool LLDir_Mac::fileExists(const std::string &filename) const -{ - return boost::filesystem::exists(filename); -} - - /*virtual*/ std::string LLDir_Mac::getLLPluginLauncher() { return gDirUtilp->getAppRODataDir() + gDirUtilp->getDirDelimiter() + diff --git a/indra/llfilesystem/lldir_mac.h b/indra/llfilesystem/lldir_mac.h index f812ee810b..54dc2eb237 100644 --- a/indra/llfilesystem/lldir_mac.h +++ b/indra/llfilesystem/lldir_mac.h @@ -45,7 +45,6 @@ public: const std::string& app_read_only_data_dir); virtual std::string getCurPath(); - virtual bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/llfilesystem/lldir_win32.cpp b/indra/llfilesystem/lldir_win32.cpp index 1cfa157634..912a2963c6 100644 --- a/indra/llfilesystem/lldir_win32.cpp +++ b/indra/llfilesystem/lldir_win32.cpp @@ -373,13 +373,6 @@ std::string LLDir_Win32::getCurPath() return ll_convert(std::wstring(w_str)); } - -bool LLDir_Win32::fileExists(const std::string &filename) const -{ - return LLFile::exists(filename); -} - - /*virtual*/ std::string LLDir_Win32::getLLPluginLauncher() { return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + diff --git a/indra/llfilesystem/lldir_win32.h b/indra/llfilesystem/lldir_win32.h index 21a3f1213b..c3a41d3e33 100644 --- a/indra/llfilesystem/lldir_win32.h +++ b/indra/llfilesystem/lldir_win32.h @@ -44,7 +44,6 @@ public: /*virtual*/ std::string getCurPath(); /*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp index 0c220fe7cf..388cbc280f 100755 --- a/indra/llfilesystem/llfilesystem.cpp +++ b/indra/llfilesystem/llfilesystem.cpp @@ -34,8 +34,6 @@ #include "llfasttimer.h" #include "lldiskcache.h" -#include "boost/filesystem.hpp" - constexpr S32 LLFileSystem::READ = 0x00000001; constexpr S32 LLFileSystem::WRITE = 0x00000002; constexpr S32 LLFileSystem::READ_WRITE = 0x00000003; // LLFileSystem::READ & LLFileSystem::WRITE @@ -51,22 +49,21 @@ LLFileSystem::LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_ mBytesRead = 0; mMode = mode; + // build the filepath + mPath = fsyspath(LLDiskCache::metaDataToFilepath(mFileID, mFileType)); + // This block of code was originally called in the read() method but after comments here: // https://bitbucket.org/lindenlab/viewer/commits/e28c1b46e9944f0215a13cab8ee7dded88d7fc90#comment-10537114 // we decided to follow Henri's suggestion and move the code to update the last access time here. if (mode == LLFileSystem::READ) { - // build the filename (TODO: we do this in a few places - perhaps we should factor into a single function) - const std::string filename = LLDiskCache::metaDataToFilepath(mFileID, mFileType); - // update the last access time for the file if it exists - this is required // even though we are reading and not writing because this is the // way the cache works - it relies on a valid "last accessed time" for // each file so it knows how to remove the oldest, unused files - bool exists = gDirUtilp->fileExists(filename); - if (exists) + if (LLFile::exists(mPath)) { - updateFileAccessTime(filename); + updateFileAccessTime(); } } } @@ -111,20 +108,11 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp return true; } -// static -S64 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type) -{ - const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type); - return LLFile::size(filename); -} - bool LLFileSystem::read(U8* buffer, S32 bytes) { bool success = false; - const std::string filename = LLDiskCache::metaDataToFilepath(mFileID, mFileType); - - llifstream file(filename, std::ios::binary); + llifstream file(mPath, std::ios::binary); if (file.is_open()) { file.seekg(mPosition, std::ios::beg); @@ -164,13 +152,11 @@ bool LLFileSystem::eof() const bool LLFileSystem::write(const U8* buffer, S32 bytes) { - const std::string filename = LLDiskCache::metaDataToFilepath(mFileID, mFileType); - bool success = false; if (mMode == APPEND) { - llofstream ofs(filename, std::ios::app | std::ios::binary); + llofstream ofs(mPath, std::ios::app | std::ios::binary); if (ofs) { ofs.write((const char*)buffer, bytes); @@ -183,7 +169,7 @@ bool LLFileSystem::write(const U8* buffer, S32 bytes) else if (mMode == READ_WRITE) { // Don't truncate if file already exists - llofstream ofs(filename, std::ios::in | std::ios::binary); + llofstream ofs(mPath, std::ios::in | std::ios::binary); if (ofs) { ofs.seekp(mPosition, std::ios::beg); @@ -194,7 +180,7 @@ bool LLFileSystem::write(const U8* buffer, S32 bytes) else { // File doesn't exist - open in write mode - ofs.open(filename, std::ios::binary); + ofs.open(mPath, std::ios::binary); if (ofs.is_open()) { ofs.write((const char*)buffer, bytes); @@ -205,7 +191,7 @@ bool LLFileSystem::write(const U8* buffer, S32 bytes) } else { - llofstream ofs(filename, std::ios::binary); + llofstream ofs(mPath, std::ios::binary); if (ofs) { ofs.write((const char*)buffer, bytes); @@ -256,7 +242,7 @@ S32 LLFileSystem::tell() const S32 LLFileSystem::getSize() const { - return (S32)LLFileSystem::getFileSize(mFileID, mFileType); + return narrow(LLFile::size(mPath)); } S32 LLFileSystem::getMaxSize() const @@ -271,17 +257,18 @@ bool LLFileSystem::rename(const LLUUID& new_id, const LLAssetType::EType new_typ mFileID = new_id; mFileType = new_type; + mPath = fsyspath(LLDiskCache::metaDataToFilepath(mFileID, mFileType)); return true; } bool LLFileSystem::remove() const { - LLFileSystem::removeFile(mFileID, mFileType); + LLFile::remove(mPath); return true; } -void LLFileSystem::updateFileAccessTime(const std::string& file_path) +void LLFileSystem::updateFileAccessTime() { /** * Threshold in time_t units that is used to decide if the last access time @@ -292,52 +279,32 @@ void LLFileSystem::updateFileAccessTime(const std::string& file_path) * * Let's start with 1 hour in time_t units and see how that unfolds */ - constexpr std::time_t time_threshold = 1 * 60 * 60; + constexpr std::chrono::hours time_threshold(1); // current time - const std::time_t cur_time = std::time(nullptr); - - boost::system::error_code ec; -#if LL_WINDOWS - // file last write time - const std::time_t last_write_time = boost::filesystem::last_write_time(ll_convert(file_path), ec); - if (ec.failed()) - { - LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; - return; - } - - // delta between cur time and last time the file was written - const std::time_t delta_time = cur_time - last_write_time; + const std::filesystem::file_time_type cur_time = std::chrono::file_clock::now(); - // we only write the new value if the time in time_threshold has elapsed - // before the last one - if (delta_time > time_threshold) - { - boost::filesystem::last_write_time(ll_convert(file_path), cur_time, ec); - } -#else + std::error_code ec; // file last write time - const std::time_t last_write_time = boost::filesystem::last_write_time(file_path, ec); - if (ec.failed()) + const std::filesystem::file_time_type last_write_time = std::filesystem::last_write_time(mPath, ec); + if (ec) { - LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; + LL_WARNS() << "Failed to read last write time for cache file " << mPath << ": " << ec.message() << LL_ENDL; return; } // delta between cur time and last time the file was written - const std::time_t delta_time = cur_time - last_write_time; + const auto delta_time = cur_time - last_write_time; // we only write the new value if the time in time_threshold has elapsed // before the last one if (delta_time > time_threshold) { - boost::filesystem::last_write_time(file_path, cur_time, ec); + std::filesystem::last_write_time(mPath, cur_time, ec); } -#endif - if (ec.failed()) + if (ec) { - LL_WARNS() << "Failed to update last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; + LL_WARNS() << "Failed to update last write time for cache file " << mPath << ": " << ec.message() << LL_ENDL; } } diff --git a/indra/llfilesystem/llfilesystem.h b/indra/llfilesystem/llfilesystem.h index 7188683e7f..bc8b9216bd 100644 --- a/indra/llfilesystem/llfilesystem.h +++ b/indra/llfilesystem/llfilesystem.h @@ -33,6 +33,7 @@ #include "lluuid.h" #include "llassettype.h" #include "lldiskcache.h" +#include class LLFileSystem { @@ -58,13 +59,12 @@ class LLFileSystem * file in the cache is read (not written) so that the last time the file was * accessed is up to date (This is used in the mechanism for purging the cache) */ - void updateFileAccessTime(const std::string& file_path); + void updateFileAccessTime(); static bool getExists(const LLUUID& file_id, const LLAssetType::EType file_type); static bool removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_warning = 0); static bool renameFile(const LLUUID& old_file_id, const LLAssetType::EType old_file_type, const LLUUID& new_file_id, const LLAssetType::EType new_file_type); - static S64 getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type); public: static const S32 READ; @@ -73,6 +73,7 @@ class LLFileSystem static const S32 APPEND; protected: + std::filesystem::path mPath; LLAssetType::EType mFileType; LLUUID mFileID; S32 mPosition; diff --git a/indra/llfilesystem/tests/lldir_test.cpp b/indra/llfilesystem/tests/lldir_test.cpp index 8b86da40b3..b879fef48a 100644 --- a/indra/llfilesystem/tests/lldir_test.cpp +++ b/indra/llfilesystem/tests/lldir_test.cpp @@ -405,7 +405,7 @@ namespace tut std::string makeTestFile( const std::string& dir, const std::string& file ) { std::string path = dir + file; - LLFILE* handle = LLFile::fopen( path, "w" ); + LLFILE* handle = LLFile::fopen(path, TEXT("w")); ensure("failed to open test file '"+path+"'", handle != NULL ); // Harbison & Steele, 4th ed., p. 366: "If an error occurs, fputs // returns EOF; otherwise, it returns some other, nonnegative value." diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp index c896d60c85..1d93014e1b 100644 --- a/indra/llimage/llimagedimensionsinfo.cpp +++ b/indra/llimage/llimagedimensionsinfo.cpp @@ -166,7 +166,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg() { sJpegErrorEncountered = false; clean(); - FILE* fp = LLFile::fopen(mSrcFilename, "rb"); + FILE* fp = LLFile::fopen(mSrcFilename, TEXT("rb")); if (!fp) { setLastError("Unable to open file for reading", mSrcFilename); diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp index 25232b77aa..7c6686db95 100644 --- a/indra/llimage/llimagetga.cpp +++ b/indra/llimage/llimagetga.cpp @@ -1191,7 +1191,7 @@ bool LLImageTGA::loadFile( const std::string& path ) return false; } - LLFILE* file = LLFile::fopen(path, "rb"); /* Flawfinder: ignore */ + LLFILE* file = LLFile::fopen(path, TEXT("rb")); /* Flawfinder: ignore */ if( !file ) { LL_WARNS() << "Couldn't open file " << path << LL_ENDL; diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 34eeacb273..13be0161b4 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -1402,7 +1402,7 @@ void LLAssetStorage::legacyGetDataCallback(const LLUUID &uuid, uuid.toString(uuid_str); filename = llformat("%s.%s",gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str(),LLAssetType::lookup(type)); - LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */ + LLFILE* fp = LLFile::fopen(filename, TEXT("wb")); /* Flawfinder: ignore */ if (fp) { const S32 buf_size = 65536; diff --git a/indra/llmessage/lltransfersourcefile.cpp b/indra/llmessage/lltransfersourcefile.cpp index 77a6c466c7..c2bf5c2afa 100644 --- a/indra/llmessage/lltransfersourcefile.cpp +++ b/indra/llmessage/lltransfersourcefile.cpp @@ -62,7 +62,7 @@ void LLTransferSourceFile::initTransfer() return; } // Look for the file. - mFP = LLFile::fopen(mParams.getFilename(), "rb"); /* Flawfinder: ignore */ + mFP = LLFile::fopen(mParams.getFilename(), TEXT("rb")); /* Flawfinder: ignore */ if (!mFP) { sendTransferStatus(LLTS_ERROR); diff --git a/indra/llmessage/lltransfertargetfile.cpp b/indra/llmessage/lltransfertargetfile.cpp index 6d8b69fa6f..cc66befcae 100644 --- a/indra/llmessage/lltransfertargetfile.cpp +++ b/indra/llmessage/lltransfertargetfile.cpp @@ -75,7 +75,7 @@ LLTSCode LLTransferTargetFile::dataCallback(const S32 packet_id, U8 *in_datap, c if (!mFP) { - mFP = LLFile::fopen(mParams.mFilename, "wb"); /* Flawfinder: ignore */ + mFP = LLFile::fopen(mParams.mFilename, TEXT("wb")); /* Flawfinder: ignore */ if (!mFP) { diff --git a/indra/llmessage/llxfer_file.cpp b/indra/llmessage/llxfer_file.cpp index 71b910297b..f0310c6297 100644 --- a/indra/llmessage/llxfer_file.cpp +++ b/indra/llmessage/llxfer_file.cpp @@ -161,7 +161,7 @@ S32 LLXfer_File::initializeRequest(U64 xfer_id, S32 LLXfer_File::startDownload() { S32 retval = 0; // presume success - mFp = LLFile::fopen(mTempFilename,"w+b"); /* Flawfinder : ignore */ + mFp = LLFile::fopen(mTempFilename,TEXT("w+b")); /* Flawfinder : ignore */ if (mFp) { fclose(mFp); @@ -209,7 +209,7 @@ S32 LLXfer_File::startSend (U64 xfer_id, const LLHost &remote_host) mBufferStartOffset = 0; // We leave the file open, assuming we'll start reading and sending soon - mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */ + mFp = LLFile::fopen(mLocalFilename,TEXT("rb")); /* Flawfinder : ignore */ if (mFp) { fseek(mFp,0,SEEK_END); @@ -252,7 +252,7 @@ S32 LLXfer_File::reopenFileHandle() if (mFp == NULL) { - mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */ + mFp = LLFile::fopen(mLocalFilename,TEXT("rb")); /* Flawfinder : ignore */ if (mFp == NULL) { LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found when re-opening file" << LL_ENDL; @@ -313,7 +313,7 @@ S32 LLXfer_File::flush() { LL_ERRS("Xfer") << "Overwriting open file pointer!" << LL_ENDL; } - mFp = LLFile::fopen(mTempFilename,"a+b"); /* Flawfinder : ignore */ + mFp = LLFile::fopen(mTempFilename,TEXT("a+b")); /* Flawfinder : ignore */ if (mFp) { @@ -381,11 +381,11 @@ S32 LLXfer_File::processEOF() } else { - //LLFILE* fp = LLFile::fopen(mTempFilename, "r"); + //LLFILE* fp = LLFile::fopen(mTempFilename, TEXT("r")); //LL_WARNS() << "File " << mTempFilename << " does " // << (!fp ? "not" : "" ) << " exit." << LL_ENDL; //if(fp) fclose(fp); - //fp = LLFile::fopen(mLocalFilename, "r"); + //fp = LLFile::fopen(mLocalFilename, TEXT("r")); //LL_WARNS() << "File " << mLocalFilename << " does " // << (!fp ? "not" : "" ) << " exit." << LL_ENDL; //if(fp) fclose(fp); @@ -452,8 +452,8 @@ U32 LLXfer_File::getXferTypeTag() S32 copy_file(const std::string& from, const std::string& to) { S32 rv = 0; - LLFILE* in = LLFile::fopen(from, "rb"); /*Flawfinder: ignore*/ - LLFILE* out = LLFile::fopen(to, "wb"); /*Flawfinder: ignore*/ + LLFILE* in = LLFile::fopen(from, TEXT("rb")); /*Flawfinder: ignore*/ + LLFILE* out = LLFile::fopen(to, TEXT("wb")); /*Flawfinder: ignore*/ if(in && out) { S32 read = 0; diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index e2937490ba..5b3b57f11e 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -2376,7 +2376,7 @@ void dump_prehash_files() { U32 i; std::string filename("../../indra/llmessage/message_prehash.h"); - LLFILE* fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */ + LLFILE* fp = LLFile::fopen(filename, TEXT("w")); /* Flawfinder: ignore */ if (fp) { fprintf( @@ -2407,7 +2407,7 @@ void dump_prehash_files() fclose(fp); } filename = std::string("../../indra/llmessage/message_prehash.cpp"); - fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */ + fp = LLFile::fopen(filename, TEXT("w")); /* Flawfinder: ignore */ if (fp) { fprintf( diff --git a/indra/llmessage/tests/lldatapacker_test.cpp b/indra/llmessage/tests/lldatapacker_test.cpp index 746817936d..92a2c31ca8 100644 --- a/indra/llmessage/tests/lldatapacker_test.cpp +++ b/indra/llmessage/tests/lldatapacker_test.cpp @@ -348,7 +348,7 @@ namespace tut { F32 f_val = 44.44f, f_unpkval; - LLFILE* fp = LLFile::fopen(TEST_FILE_NAME, "w+"); + LLFILE* fp = LLFile::fopen(TEST_FILE_NAME, TEXT("w+")); if(!fp) { LL_ERRS() << "File couldnt be open" << LL_ENDL; @@ -403,7 +403,7 @@ namespace tut LLVector4 unpkllvec4; LLUUID unpkuuid; - LLFILE* fp = LLFile::fopen(TEST_FILE_NAME,"w+"); + LLFILE* fp = LLFile::fopen(TEST_FILE_NAME,TEXT("w+")); if(!fp) { LL_ERRS() << "File couldnt be open" << LL_ENDL; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 7e8d31232b..0ed98f2e7e 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -501,7 +501,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev open_file_name = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/errorF.glsl"); } - file = LLFile::fopen(open_file_name, "r"); + file = LLFile::fopen(open_file_name, TEXT("r")); } else #endif @@ -529,7 +529,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev */ LL_DEBUGS("ShaderLoading") << "Looking in " << open_file_name << LL_ENDL; - file = LLFile::fopen(open_file_name, "r"); /* Flawfinder: ignore */ + file = LLFile::fopen(open_file_name, TEXT("r")); /* Flawfinder: ignore */ if (file) { LL_DEBUGS("ShaderLoading") << "Loading file: " << open_file_name << " (Want class " << gpu_class << ")" << LL_ENDL; diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp index a792cb8103..206d02b366 100644 --- a/indra/llui/lluicolortable.cpp +++ b/indra/llui/lluicolortable.cpp @@ -298,7 +298,7 @@ void LLUIColorTable::saveUserSettings() const if(!output_node->isNull()) { const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "colors.xml"); - LLFILE *fp = LLFile::fopen(filename, "w"); + LLFILE *fp = LLFile::fopen(filename, TEXT("w")); if(fp != NULL) { diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp index 8fd85a89a1..e3d806bdd0 100644 --- a/indra/llui/llxuiparser.cpp +++ b/indra/llui/llxuiparser.cpp @@ -637,7 +637,7 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p } } - LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), "w"); + LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), TEXT("w")); LLXMLNode::writeHeaderToFile(xsd_file); root_nodep->writeToFile(xsd_file); fclose(xsd_file); @@ -1326,7 +1326,7 @@ void LLXUIParser::parserError(const std::string& message) struct ScopedFile { - ScopedFile( const std::string& filename, const char* accessmode ) + ScopedFile( const std::string& filename, const LLFile::fopen_flags_t* accessmode ) { mFile = LLFile::fopen(filename, accessmode); } @@ -1397,7 +1397,7 @@ bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBl mCurReadDepth = 0; setParseSilently(silent); - ScopedFile file(filename, "rb"); + ScopedFile file(filename, TEXT("rb")); if( !file.isOpen() ) { LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL; diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 562a30e8d1..a8e44f7bdd 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -399,7 +399,7 @@ void LLControlGroup::cleanup() if(mSettingsProfile && getCount.size() != 0) { std::string file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, SETTINGS_PROFILE); - LLFILE* out = LLFile::fopen(file, "w"); /* Flawfinder: ignore */ + LLFILE* out = LLFile::fopen(file, TEXT("w")); /* Flawfinder: ignore */ if(!out) { LL_WARNS("SettingsProfile") << "Error opening " << SETTINGS_PROFILE << LL_ENDL; diff --git a/indra/llxml/llxmlparser.cpp b/indra/llxml/llxmlparser.cpp index e2c7d17e2a..5aac9100dd 100644 --- a/indra/llxml/llxmlparser.cpp +++ b/indra/llxml/llxmlparser.cpp @@ -72,7 +72,7 @@ bool LLXmlParser::parseFile(const std::string &path) bool success = true; - LLFILE* file = LLFile::fopen(path, "rb"); /* Flawfinder: ignore */ + LLFILE* file = LLFile::fopen(path, TEXT("rb")); /* Flawfinder: ignore */ if( !file ) { mAuxErrorString = llformat( "Couldn't open file %s", path.c_str()); @@ -388,7 +388,7 @@ int main() { char buf[1024]; - LLFILE* file = LLFile::fopen("test.xml", "rb"); + LLFILE* file = LLFile::fopen("test.xml", TEXT("rb")); if( !file ) { return 1; diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 4a4985d8ac..63a3743ef7 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -512,7 +512,7 @@ bool LLConversationLog::saveToFile(const std::string& filename) return false; } - LLFILE* fp = LLFile::fopen(filename, "wb"); + LLFILE* fp = LLFile::fopen(filename, TEXT("wb")); if (!fp) { LL_WARNS() << "Couldn't open call log list" << filename << LL_ENDL; @@ -556,7 +556,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) return false; } - LLFILE* fp = LLFile::fopen(filename, "rb"); + LLFILE* fp = LLFile::fopen(filename, TEXT("rb")); if (!fp) { LL_WARNS() << "Couldn't open call log list" << filename << LL_ENDL; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 6c151351ff..200fce7b5b 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -114,7 +114,7 @@ void LLStandardBumpmap::addstandard() gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness"); // BE_DARKNESS std::string file_name = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "std_bump.ini" ); - LLFILE* file = LLFile::fopen( file_name, "rt" ); /*Flawfinder: ignore*/ + LLFILE* file = LLFile::fopen( file_name, TEXT("rt") ); /*Flawfinder: ignore*/ if( !file ) { LL_WARNS() << "Could not open std_bump <" << file_name << ">" << LL_ENDL; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 4fa14a199d..989dbc0c29 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -2037,9 +2037,13 @@ void LLFloaterPreference::changed() { // onClearLog clears list, then notifies changed() and only then clears file, // so check presence of conversations before checking file, file will cleared later. - bool has_logs = LLConversationLog::instance().getConversations().size() > 0 - && LLFile::isfile(LLConversationLog::instance().getFileName()) - && LLFile::size(LLConversationLog::instance().getFileName()) > 0; + bool has_logs = false; + if (LLConversationLog::instance().getConversations().size() > 0) + { + std::filesystem::path file_path = fsyspath(LLConversationLog::instance().getFileName()); + has_logs = LLFile::isfile(file_path) + && LLFile::size(file_path) > 0; + } getChild("clear_log")->setEnabled(has_logs); } diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 0bf0946c42..cf710d45dd 100755 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -574,7 +574,7 @@ void LLFloaterUIPreview::onClickExportSchema() // std::string file_name(template_path + gDirUtilp->getDirDelimiter() + widget_name + ".rng"); - // LLFILE* rng_file = LLFile::fopen(file_name.c_str(), "w"); + // LLFILE* rng_file = LLFile::fopen(file_name.c_str(), TEXT("w")); // { // LLXMLNode::writeHeaderToFile(rng_file); // const bool use_type_decorations = false; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 043fd7003d..9491c9d610 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -2745,7 +2745,7 @@ bool LLInventoryModel::loadSkeleton( const S32 NO_VERSION = LLViewerInventoryCategory::VERSION_UNKNOWN; std::string gzip_filename(inventory_filename); gzip_filename.append(".gz"); - LLFILE* fp = LLFile::fopen(gzip_filename, "rb"); + LLFILE* fp = LLFile::fopen(gzip_filename, TEXT("rb")); bool remove_inventory_file = false; if (LLAppViewer::instance()->isSecondInstance()) { @@ -4908,7 +4908,7 @@ bool decompress_file(const char* src_filename, const char* dst_filename) // open the files src = gzopen(src_filename, "rb"); if(!src) goto err_decompress; - dst = LLFile::fopen(dst_filename, "wb"); + dst = LLFile::fopen(dst_filename, TEXT("wb")); if(!dst) goto err_decompress; // decompress. diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 666ab4f5d0..458d5225e1 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -575,7 +575,7 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) // Write the resulting XML to file if (!output_node->isNull()) { - LLFILE *fp = LLFile::fopen(filename, "w"); + LLFILE *fp = LLFile::fopen(filename, TEXT("w")); if (fp != NULL) { LLXMLNode::writeHeaderToFile(fp); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 30ea255e24..405530f5bd 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -453,7 +453,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m // If we got here, we managed to stat the file. // Open the file to read in binary mode to prevent interpreting other characters as EOF - LLFILE* fptr = LLFile::fopen(log_file_name, "rb"); /*Flawfinder: ignore*/ + LLFILE* fptr = LLFile::fopen(log_file_name, TEXT("rb")); /*Flawfinder: ignore*/ if (!fptr) { // Ok, this is strange but not really tragic in the big picture of things LL_WARNS("ChatHistory") << "Unable to read file " << log_file_name << " after stat was successful" << LL_ENDL; @@ -890,7 +890,7 @@ bool LLLogChat::isAdHocTranscriptExist(std::string file_name) bool LLLogChat::isTranscriptFileFound(std::string fullname) { bool result = false; - LLFILE * filep = LLFile::fopen(fullname, "rb"); + LLFILE * filep = LLFile::fopen(fullname, TEXT("rb")); if (NULL != filep) { if (makeLogFileName("chat") == fullname) @@ -1183,7 +1183,7 @@ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::listgetExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "render_mute_settings.txt"); - LLFILE* fp = LLFile::fopen(filename, "wb"); + LLFILE* fp = LLFile::fopen(filename, TEXT("wb")); if (!fp) { LL_WARNS() << "Couldn't open render mute list file: " << filename << LL_ENDL; @@ -963,7 +963,7 @@ bool LLRenderMuteList::saveToFile() bool LLRenderMuteList::loadFromFile() { std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "render_mute_settings.txt"); - LLFILE* fp = LLFile::fopen(filename, "rb"); + LLFILE* fp = LLFile::fopen(filename, TEXT("rb")); if (!fp) { LL_WARNS() << "Couldn't open render mute list file: " << filename << LL_ENDL; diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 4fe661b055..6928d7e6c3 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -801,7 +801,7 @@ bool LLPreviewNotecard::loadNotecardText(const std::string& filename) return false; } - LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ + LLFILE* file = LLFile::fopen(filename, TEXT("rb")); /*Flawfinder: ignore*/ if (!file) { LL_WARNS() << "Error opening " << filename << LL_ENDL; @@ -832,7 +832,7 @@ bool LLPreviewNotecard::loadNotecardText(const std::string& filename) bool LLPreviewNotecard::writeToFile(const std::string& filename) { - LLFILE* fp = LLFile::fopen(filename, "wb"); + LLFILE* fp = LLFile::fopen(filename, TEXT("wb")); if (!fp) { LL_WARNS() << "Unable to write to " << filename << LL_ENDL; diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 2c436198e3..c73976e540 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -632,7 +632,7 @@ bool LLScriptEdCore::loadScriptText(const std::string& filename) return false; } - LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ + LLFILE* file = LLFile::fopen(filename, TEXT("rb")); /*Flawfinder: ignore*/ if (!file) { LL_WARNS() << "Error opening " << filename << LL_ENDL; @@ -663,7 +663,7 @@ bool LLScriptEdCore::loadScriptText(const std::string& filename) bool LLScriptEdCore::writeToFile(const std::string& filename) { - LLFILE* fp = LLFile::fopen(filename, "wb"); + LLFILE* fp = LLFile::fopen(filename, TEXT("wb")); if (!fp) { LL_WARNS() << "Unable to write to " << filename << LL_ENDL; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 3ce9526488..37609f74ed 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -587,7 +587,7 @@ bool idle_startup() std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg"); LLFILE* found_template = NULL; - found_template = LLFile::fopen(message_template_path, "r"); /* Flawfinder: ignore */ + found_template = LLFile::fopen(message_template_path, TEXT("r")); /* Flawfinder: ignore */ #if LL_WINDOWS // On the windows dev builds, unpackaged, the message_template.msg @@ -596,7 +596,7 @@ bool idle_startup() if (!found_template) { message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg"); - found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ + found_template = LLFile::fopen(message_template_path.c_str(), TEXT("r")); /* Flawfinder: ignore */ } #elif LL_DARWIN // On Mac dev builds, message_template.msg lives in: @@ -606,7 +606,7 @@ bool idle_startup() message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "message_template.msg"); - found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ + found_template = LLFile::fopen(message_template_path.c_str(), TEXT("r")); /* Flawfinder: ignore */ } #endif diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index c1ec5fa183..d1e36676af 100644 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -420,7 +420,7 @@ void LLToolBarView::saveToolbars() const if(!output_node->isNull()) { const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "toolbars.xml"); - LLFILE *fp = LLFile::fopen(filename, "w"); + LLFILE *fp = LLFile::fopen(filename, TEXT("w")); if (fp != NULL) { LLXMLNode::writeHeaderToFile(fp); diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index e76d340eda..c28f3dc73a 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -182,7 +182,7 @@ void LLViewerAssetStorage::storeAssetData( else { // LLAssetStorage metric: Successful Request - S32 size = (S32)LLFileSystem::getFileSize(asset_id, asset_type); + S32 size = vfile.getSize(); const char *message = "Added to upload queue"; reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, size, MR_OKAY, __FILE__, __LINE__, message ); @@ -279,7 +279,7 @@ void LLViewerAssetStorage::storeAssetData( LL_DEBUGS("AssetStorage") << "ASSET_ID: " << asset_id << LL_ENDL; S32 size = 0; - LLFILE* fp = LLFile::fopen(filename, "rb"); + LLFILE* fp = LLFile::fopen(filename, TEXT("rb")); if (fp) { fseek(fp, 0, SEEK_END); diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 3c79f0b21c..9b39f7b0e9 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1430,7 +1430,7 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename) // file in app_settings is supposed to be up to date // this is only for the file from user_settings LL_INFOS("ViewerInput") << "Updating file " << filename << " to a newer version" << LL_ENDL; - LLFILE *fp = LLFile::fopen(filename, "w"); + LLFILE *fp = LLFile::fopen(filename, TEXT("w")); if (fp != NULL) { LLXMLNode::writeHeaderToFile(fp); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 0e9bfb102f..a8ed2da9e0 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -1161,7 +1161,7 @@ void handle_compress_image() // so doing dirty, but OS independent fopen and fseek size_t get_file_size(std::string &filename) { - LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ + LLFILE* file = LLFile::fopen(filename, TEXT("rb")); /*Flawfinder: ignore*/ if (!file) { LL_WARNS() << "Error opening " << filename << LL_ENDL; diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp index 58065ecce5..a2141f4eed 100644 --- a/indra/newview/llviewerstatsrecorder.cpp +++ b/indra/newview/llviewerstatsrecorder.cpp @@ -194,7 +194,7 @@ void LLViewerStatsRecorder::writeToLog( F32 interval ) // Open the data file makeStatsFileName(); - mStatsFile = LLFile::fopen(mStatsFileName, "wb"); + mStatsFile = LLFile::fopen(mStatsFileName, TEXT("wb")); if (mStatsFile) { -- cgit v1.3