From 13a3cf92ca9e647dfc39e761ce0068aa021ca657 Mon Sep 17 00:00:00 2001 From: Frederick Martian Date: Fri, 28 Nov 2025 13:30:36 +0100 Subject: - Improve documentation of LLFile functions and methods - Improve error handling in LLFile::read(), LLFile::write() and LLFile::copy() - Improve LLFileSystem::getFileSize() to work with the extra possibility of LLFile::size() returning -1 on error - Replace LLAPRFile:readEx() and LLAPRFile::writeEx() with according LLFile functions --- indra/llcommon/llfile.cpp | 119 ++++++++-------- indra/llcommon/llfile.h | 266 ++++++++++++++++++++---------------- indra/llfilesystem/llfilesystem.cpp | 4 +- indra/newview/lltexturecache.cpp | 62 +++++---- 4 files changed, 243 insertions(+), 208 deletions(-) diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index 6ccf01dd78..cb3357419a 100755 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -29,7 +29,6 @@ #include "linden_common.h" #include "llfile.h" -#include "llstring.h" #include "llerror.h" #include "stringize.h" @@ -236,7 +235,7 @@ static int warnif(const std::string& desc, const std::string& filename, int rc, // For certain operations, a particular errno value might be // acceptable -- e.g. stat() could permit ENOENT, mkdir() could permit - // EEXIST. Don't warn if caller explicitly says this errno is okay. + // EEXIST. Don't log a warning if caller explicitly says this errno is okay. if (errn != accept) { LL_WARNS("LLFile") << "Couldn't " << desc << " '" << filename << "' (errno " << errn << "): " << strerr(errn) << LL_ENDL; @@ -910,22 +909,29 @@ S64 LLFile::read(const std::string& filename, void* buf, S64 offset, S64 nbytes, return 0; } - std::ios_base::openmode omode = LLFile::in | LLFile::binary; - - LLFile file(filename, omode, ec); - if (file) + if (!buf || offset < 0) { - S64 bytes_read = 0; - if (offset > 0) - { - file.seek(offset, ec); - } - if (!ec) + set_ec_to_parameter_error(ec); + } + else + { + std::ios_base::openmode omode = LLFile::in | LLFile::binary; + + LLFile file(filename, omode, ec); + if (file) { - bytes_read = file.read(buf, nbytes, ec); + S64 bytes_read = 0; + if (offset > 0) + { + file.seek(offset, ec); + } if (!ec) { - return bytes_read; + bytes_read = file.read(buf, nbytes, ec); + if (!ec) + { + return bytes_read; + } } } } @@ -949,26 +955,33 @@ S64 LLFile::write(const std::string& filename, const void* buf, S64 offset, S64 return 0; } - std::ios_base::openmode omode = LLFile::out | LLFile::binary; - if (offset < 0) + if (!buf) { - omode |= LLFile::app; + set_ec_to_parameter_error(ec); } - - LLFile file(filename, omode, ec); - if (file) + else { - S64 bytes_written = 0; - if (offset > 0) + std::ios_base::openmode omode = LLFile::out | LLFile::binary; + if (offset < 0) { - file.seek(offset, ec); + omode |= LLFile::app; } - if (!ec) + + LLFile file(filename, omode, ec); + if (file) { - bytes_written = file.write(buf, nbytes, ec); + S64 bytes_written = 0; + if (offset > 0) + { + file.seek(offset, ec); + } if (!ec) { - return bytes_written; + bytes_written = file.write(buf, nbytes, ec); + if (!ec) + { + return bytes_written; + } } } } @@ -976,15 +989,21 @@ S64 LLFile::write(const std::string& filename, const void* buf, S64 offset, S64 } // static -bool LLFile::copy(const std::string& from, const std::string& to) +bool LLFile::copy(const std::string& source, const std::string& target) { std::error_code ec; - std::filesystem::path from_path = utf8StringToPath(from); - std::filesystem::path to_path = utf8StringToPath(to); - bool copied = std::filesystem::copy_file(from_path, to_path, 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); + bool copied = std::filesystem::copy_file(source_path, target_path, options, ec); if (!copied) { - LL_WARNS("LLFile") << "copy failed" << LL_ENDL; + warnif(STRINGIZE("copy failed, to '" << target << "' from"), source, ec); } return copied; } @@ -1004,7 +1023,7 @@ int LLFile::stat(const std::string& filename, llstat* filestatus, const char *fn // static std::time_t LLFile::getCreationTime(const std::string& filename, int suppress_warning) { - // As if C++20 there is no functionality in std::filesystem to retrieve this information + // 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) @@ -1046,7 +1065,7 @@ S64 LLFile::size(const std::string& filename, int suppress_warning) std::error_code ec; std::filesystem::path file_path = utf8StringToPath(filename); std::intmax_t size = (std::intmax_t)std::filesystem::file_size(file_path, ec); - return warnif("size", filename, ec, suppress_warning) ? -1 : size; + return warnif("size", filename, ec, suppress_warning) ? 0 : size; } // static @@ -1057,13 +1076,13 @@ std::filesystem::file_status LLFile::getStatus(const std::string& filename, bool std::filesystem::file_status status; if (dontFollowSymLink) { - status = std::filesystem::status(file_path, ec); + status = std::filesystem::symlink_status(file_path, ec); } else { - status = std::filesystem::symlink_status(file_path, ec); + status = std::filesystem::status(file_path, ec); } - warnif("getattr", filename, ec, suppress_warning); + warnif("getStatus()", filename, ec, suppress_warning); return status; } @@ -1155,10 +1174,8 @@ void llifstream::open(const std::string& _Filename, ios_base::openmode _Mode) _Mode | ios_base::in); } - /************** output file stream ********************************/ - llofstream::llofstream() {} // explicit @@ -1174,30 +1191,4 @@ void llofstream::open(const std::string& _Filename, ios_base::openmode _Mode) _Mode | ios_base::out); } -/************** helper functions ********************************/ - -std::streamsize llifstream_size(llifstream& ifstr) -{ - if(!ifstr.is_open()) return 0; - std::streampos pos_old = ifstr.tellg(); - ifstr.seekg(0, std::ios_base::beg); - std::streampos pos_beg = ifstr.tellg(); - ifstr.seekg(0, std::ios_base::end); - std::streampos pos_end = ifstr.tellg(); - ifstr.seekg(pos_old, std::ios_base::beg); - return pos_end - pos_beg; -} - -std::streamsize llofstream_size(llofstream& ofstr) -{ - if(!ofstr.is_open()) return 0; - std::streampos pos_old = ofstr.tellp(); - ofstr.seekp(0, std::ios_base::beg); - std::streampos pos_beg = ofstr.tellp(); - ofstr.seekp(0, std::ios_base::end); - std::streampos pos_end = ofstr.tellp(); - ofstr.seekp(pos_old, std::ios_base::beg); - return pos_end - pos_beg; -} - #endif // LL_WINDOWS diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index 2bfc4d1ffb..ae8e755fe7 100755 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -53,19 +53,25 @@ typedef FILE LLFILE; #include "llstring.h" // safe char* -> std::string conversion +/// 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 { public: - //-------------------------------------------------------------------------------------- - // constants - //-------------------------------------------------------------------------------------- - // These can be passed to the omode parameter of LLFile::open() and its constructor - /* + // ================================================================================ + /// @name Constants + /// + ///@{ + /** These can be passed to the omode parameter of LLFile::open() and its constructor + This is similar to the openmode flags for std:fstream but not exactly the same std::fstream open() does not allow to open a file for writing without either forcing the file to be truncated on open or all write operations being always - appended to the end of the file. + appended to the end of the file or failing to open when the file does not exist. But to allow implementing the LLAPRFile::writeEx() functionality we need to be able to write at a random position to the file without truncating it on open. @@ -104,65 +110,71 @@ public: static const std::ios_base::openmode trunc = 1 << 6; // truncate on open static const std::ios_base::openmode noreplace = 1 << 7; // no replace if it exists - // Additional optional omode flags to open() and lmode to fopen() or mode flags to lock() - // to indicate which sort of lock if any to attempt to get + /// Additional optional flags to omode in open() and lmode in fopen() or lock() + /// to indicate which sort of lock if any to attempt to get + /// + /// NOTE: there is a fundamental difference between platforms. + /// On Windows this lock is mandatory as it is part of the API to open a file handle and other + /// processes can not avoid it. If a file was opened denying other processes read and/or write + /// access, trying to open the same file in another process with that access will fail. + /// On Mac and Linux it is only an advisory lock implemented through the flock() system call. + /// This means that any other application needs to also attempt to at least acquire a shared + /// lock on the file in order to notice that the file is actually already locked. It can + /// therefore not be used to prevent random other applications from accessing the file, but it + /// works for other viewer processes when they use either the LLFile::open() or LLFile::fopen() + /// functions with the appropriate lock flags to open a file. static const std::ios_base::openmode exclusive = 1 << 16; static const std::ios_base::openmode shared = 1 << 17; - // When used either in omode for LLFile::open() or in lmode for LLFile::fopen() there is a - // difference between platforms. - // On Windows this lock is mandatory as it is part of the API to open a file and other processes - // can not avoid it. If a file was opened denying other processes read and/or write access, - // trying to open the same file with that access will fail. - // On Mac and Linux it is only an advisory lock. This means that the other application - // needs to also attempt to at least acquire a shared lock on the file in order to notice that - // the file is actually already locked. It can therefore not be used to prevent random other - // applications from accessing the file, but it works for other viewer processes when they use - // either the LLFile::open() or LLFile::fopen() functions with the appropriate lock flags to - // open a file. - - // Additional mode flag to indicate to rather fail instead of blocking when trying - // to acquire a lock with LLFile::lock() + + /// Additional lmode flag to indicate to rather fail instead of blocking when trying + /// to acquire a lock with LLFile::lock() static const std::ios_base::openmode noblock = 1 << 18; + /// The mask value for the lock mask bits static const std::ios_base::openmode lock_mask = exclusive | shared; - // These can be passed to the dir parameter of LLFile::seek() + /// One of these can be passed to the dir parameter of LLFile::seek() static const std::ios_base::seekdir beg = std::ios_base::beg; static const std::ios_base::seekdir cur = std::ios_base::cur; static const std::ios_base::seekdir end = std::ios_base::end; + ///@} - //-------------------------------------------------------------------------------------- - // constructor/deconstructor - //-------------------------------------------------------------------------------------- + // ================================================================================ + /// @name constructor/deconstructor + /// + ///@{ + /// default constructor LLFile() : mHandle(InvalidHandle) {} - // no copy + /// no copy constructor LLFile(const LLFile&) = delete; - // move construction + /// move constructor LLFile(LLFile&& other) noexcept { mHandle = other.mHandle; other.mHandle = InvalidHandle; } - // open a file + /// constructor opening the file LLFile(const std::string& filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666) : mHandle(InvalidHandle) { open(filename, omode, ec, perm); } - // Make it a RAII class + /// destructor always attempts to close the file ~LLFile() { close(); } + ///@} - //-------------------------------------------------------------------------------------- - // operators - //-------------------------------------------------------------------------------------- - // copy assignment deleted + // ================================================================================ + /// @name operators + /// + ///@{ + /// copy assignment deleted LLFile& operator=(const LLFile&) = delete; - // move assignment + /// move assignment LLFile& operator=(LLFile&& other) noexcept { close(); @@ -173,13 +185,17 @@ public: // detect whether the wrapped file descriptor/handle is open or not explicit operator bool() const { return (mHandle != InvalidHandle); } bool operator!() { return (mHandle == InvalidHandle); } + ///@} - //-------------------------------------------------------------------------------------- - // class member methods - //-------------------------------------------------------------------------------------- - - /// All of these functions take as one of their parameters a std::error_code object which can be used to + /// ================================================================================ + /// @name class member methods + /// + /// These methods provide read and write support as well as additional functionality to query the size of + /// the file, change the position of the the current file pointer or query it. + /// + /// Most of these functions take as one of their parameters a std::error_code object which can be used to /// determine in more detail what error occurred if required + ///@{ /// 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); @@ -189,7 +205,7 @@ public: S64 size(std::error_code& ec); ///< @returns the number of bytes in the file or -1 on failure - /// Return the current file pointer into the file + /// Query the position of the current file pointer in the file S64 tell(std::error_code& ec); ///< @returns the absolute offset of the file pointer in bytes relative to the start of the file or -1 on failure @@ -201,76 +217,78 @@ public: int seek(S64 offset, std::ios_base::seekdir dir, std::error_code& ec); ///< @returns 0 on success, -1 on failure - /// Read a number of bytes into the buffer starting at the current file pointer + /// Read the specified number of bytes into the buffer starting at the current file pointer S64 read(void* buffer, S64 nbytes, std::error_code& ec); ///< If the file ends before the requested amount of bytes could be read, the function succeeds and - /// returns the bytes up to the end of the file. The return value indicates the number of actually - /// read bytes and can be therefore smaller than the requested amount. - /// @returns the number of bytes read from the file or -1 on failure + /// returns the bytes up to the end of the file. The return value indicates the number of actually + /// read bytes and can be therefore smaller than the requested amount. + /// @returns the number of bytes read from the file or -1 on failure - /// Write a number of bytes to the file starting at the current file pointer + /// Write the specified number of bytes to the file starting at the current file pointer S64 write(const void* buffer, S64 nbytes, std::error_code& ec); - /// @returns the number of bytes written to the file or -1 on failure + ///< @returns the number of bytes written to the file or -1 on failure - /// Write into the file starting at the current file pointer using printf style format + /// Write into the file starting at the current file pointer using printf style format and + /// additional optional parameters as specified in the fmt string S64 printf(const char* fmt, ...); - /// @returns the number of bytes written to the file or -1 on failure + ///< @returns the number of bytes written to the file or -1 on failure /// Attempt to acquire or release a lock on the file - int lock(int mode, std::error_code& ec); - ///< mode can be one of LLFile::exclusive or LLFile::shared to acquire the according lock - /// or 0 to give up an earlier acquired lock. Adding LLFile::noblock together with one of - /// the lock requests will cause the function to fail if the lock can not be acquired, - /// otherwise the function will block until the lock can be acquired. - /// @returns 0 on success, -1 on failure + int lock(int lmode, std::error_code& ec); + ///< lmode can be one of LLFile::exclusive or LLFile::shared to acquire the according lock + /// or 0 to give up an earlier acquired lock. Adding LLFile::noblock together with one of + /// the lock requests will cause the function to fail if the lock can not be acquired, + /// otherwise the function will block until the lock can be acquired. + /// @returns 0 on success, -1 on failure /// close the file explicitely int close(std::error_code& ec); ///< @returns 0 on success, -1 on failure - /// Convinience function to close the file without parameters + /// Convenience function to close the file without additional parameters int close(); ///< @returns 0 on success, -1 on failure + ///@} - //---------------------------------------------------------------------------------------- - // static member functions - // - // All filename parameters are UTF8 file paths - // - //---------------------------------------------------------------------------------------- + /// ================================================================================ + /// @name static member functions + /// + /// These functions are static and operate with UTF8 filenames as one of their parameters. + /// + ///@{ /// open a file with the specified access mode static LLFILE* fopen(const std::string& filename, const char* 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 - /// "w" open the file for reading and writing and truncate it to zero length - /// "w+" open or create the file for reading and writing and truncate to zero length if it existed - /// "a" open the file for reading and writing and and before every write position the stream at the end of the file - /// "a+" open or create the file for reading and writing and before every write position the stream at the end of the file + /// "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 + /// "w" open the file for reading and writing and truncate it to zero length + /// "w+" open or create the file for reading and writing and truncate to zero length if it existed + /// "a" open the file for reading and writing and before every write position the stream at the end of the file + /// "a+" open or create the file for reading and writing and before every write position the stream at the end of the file /// - /// in addition to these values, "b" can be appended to indicate binary stream access, but on Linux and Mac - /// this is strictly for compatibility and has no effect. On Windows this makes the file functions not - /// try to translate line endings. Windows also allows to append "t" to indicate text mode. If neither - /// "b" or "t" is defined, Windows uses the value set by _fmode which by default is _O_TEXT. - /// This means that it is always a good idea to append "b" specifically for binary file access to - /// avoid corruption of the binary consistency of the data stream when reading or writing - /// Other characters in 'accessmode', while possible on some platforms (Windows), will usually - /// cause an error as fopen will verify this parameter + /// in addition to these values, "b" can be appended to indicate binary stream access, but on Linux and Mac + /// this is strictly for compatibility and has no effect. On Windows this makes the file functions not + /// try to translate line endings. Windows also allows to append "t" to indicate text mode. If neither + /// "b" or "t" is defined, Windows uses the value set by _fmode which by default is _O_TEXT. + /// This means that it is always a good idea to append "b" specifically for binary file access to + /// avoid corruption of the binary consistency of the data stream when reading or writing + /// Other characters in 'accessmode', while possible on some platforms (Windows), will usually + /// cause an error on other platforms as fopen will verify this parameter /// - /// lmode is optional and allows to lock the file for other processes either as a shared lock or an - /// exclusive lock. If the requested lock conflicts with an already existing lock, the open fails. - /// Pass either LLFIle::exclusive or LLFile::shared to this parameter if you want to prevent other - /// processes from reading (exclusive lock) or writing (shared lock) to the file. It will always use - /// LLFile::noblock, meaning the open will immediately fail if it conflicts with an existing lock on the - /// file. + /// lmode is optional and allows to lock the file for other processes either as a shared lock or an + /// exclusive lock. If the requested lock conflicts with an already existing lock, the open fails. + /// Pass either LLFIle::exclusive or LLFile::shared to this parameter if you want to prevent other + /// processes from reading (exclusive lock) or writing (shared lock) to the file. It will always use + /// LLFile::noblock, meaning the open will immediately fail if it conflicts with an existing lock on the + /// file. /// - /// @returns a valid LLFILE* pointer on success that can be passed to the fread() and fwrite() functions - /// and some other f functions in the Standard C library that accept a FILE* as parameter - /// or NULL on failure + /// @returns a valid LLFILE* pointer on success that can be passed to the fread() and fwrite() functions + /// and some other f functions in the Standard C library that accept a FILE* as parameter + /// or NULL on failure /// Close a file handle opened with fopen() above static int close(LLFILE * file); - /// @returns 0 on success and -1 on failure. + ///< @returns 0 on success and -1 on failure. /// create a directory static int mkdir(const std::string& filename); @@ -288,27 +306,42 @@ public: ///< 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 - /// under Windows at this time. It may do it in the same way but the used Windows API - /// does not make such guarantees. + /// under Windows at this time. It may do it in the same way but the used Windows + /// APIs do not make such guarantees. /// @returns 0 on success and -1 on failure. - /// copy the contents of the file from 'from' to 'to' filename - static bool copy(const std::string& from, const std::string& to); - ///< @returns true on success and false on failure. + /// copy the contents of the file from 'source' to 'target' + static bool copy(const std::string& source, const std::string& target); + ///< 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 + /// already existing target file. Consider using the function below if you desire a different + /// behavior when the target file already exists + /// @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); + ///< 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 + /// std::filesystem::copy_options::skip_existing - skip the operation and do not overwrite file + /// std::filesystem::copy_options::overwrite_existing - overwrite the file + /// std::filesystem::copy_options::update_existing - overwrite the file only if it is older than the file being copied + /// @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); - ///< @returns the content of the file or an empty string on failure + ///< @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); + 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); ///< @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); + 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); ///< A negative offset will append the data to the end of the file /// @returns bytes written on success, or -1 on failure @@ -321,7 +354,16 @@ public: /// get the creation data and time of a file static std::time_t getCreationTime(const std::string& filename, int suppress_warning = 0); - ///< @returns the creation time of the file or 0 on error + ///< 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); @@ -332,7 +374,7 @@ public: ///< dontFollowSymLinks set to true returns the attributes 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 - /// @returns a std::filesystem::file_status value that can be passed to the according std::filesystem::exists() + /// @returns a std::filesystem::file_status value that can be passed to the appropriate std::filesystem::exists() /// and other APIs accepting a file_status. /// get the size of a file in bytes @@ -342,19 +384,19 @@ public: /// @returns the file size on success or -1 on failure. /// check if filename is an existing file or directory - static bool exists(const std::string& filename); + static bool exists(const std::string& filename); ///< @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); + static bool isdir(const std::string& filename); ///< @returns true if the path is for an existing directory /// check if filename is an existing file - static bool isfile(const std::string& filename); + static bool isfile(const std::string& filename); ///< @returns true if the path is for an existing file /// check if filename is a symlink - static bool islink(const std::string& filename); + static bool islink(const std::string& filename); ///< @returns true if the path is pointing at a symlink /// return a path to the temporary directory on the system @@ -363,6 +405,7 @@ public: /// 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 @@ -373,9 +416,9 @@ private: const llfile_handle_t InvalidHandle = -1; #endif - //---------------------------------------------------------------------------------------- - // static member functions - //---------------------------------------------------------------------------------------- + /// ================================================================================ + /// @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); @@ -393,7 +436,7 @@ private: /// /// @returns the path as a std::wstring path #endif - llfile_handle_t mHandle; + llfile_handle_t mHandle; // The file handle/descriptor std::ios_base::openmode mOpen; // Used to emulate std::ios_base::app under Windows }; @@ -485,17 +528,6 @@ class LL_COMMON_API llofstream : public std::ofstream ios_base::openmode _Mode = ios_base::out|ios_base::trunc); }; - -/** - * @brief filesize helpers. - * - * The file size helpers are not considered particularly efficient, - * and should only be used for config files and the like -- not in a - * loop. - */ -std::streamsize LL_COMMON_API llifstream_size(llifstream& fstr); -std::streamsize LL_COMMON_API llofstream_size(llofstream& fstr); - #else // ! LL_WINDOWS // on non-windows, llifstream and llofstream are just mapped directly to the std:: equivalents diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp index 4238dd64e9..087daf78be 100755 --- a/indra/llfilesystem/llfilesystem.cpp +++ b/indra/llfilesystem/llfilesystem.cpp @@ -114,8 +114,8 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp S32 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type) { const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type); - - return (S32)LLFile::size(filename); + S64 fileSize = LLFile::size(filename); + return (fileSize > 0) ? (S32)fileSize : 0; } bool LLFileSystem::read(U8* buffer, S32 bytes) diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index ef7542fe2e..1b63739f79 100755 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -210,7 +210,8 @@ bool LLTextureCacheLocalFileWorker::doRead() } mReadData = (U8*)ll_aligned_malloc_16(mDataSize); - S32 bytes_read = LLAPRFile::readEx(mFileName, mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool()); +// S32 bytes_read = LLAPRFile::readEx(mFileName, mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool()); + S32 bytes_read = (S32)LLFile::read(mFileName, mReadData, mOffset, mDataSize); if (bytes_read != mDataSize) { @@ -346,11 +347,15 @@ bool LLTextureCacheRemoteWorker::doRead() if (mReadData) { - S32 bytes_read = LLAPRFile::readEx( local_filename, - mReadData, - mOffset, - mDataSize, - mCache->getLocalAPRFilePool()); +// S32 bytes_read = LLAPRFile::readEx(local_filename, +// mReadData, +// mOffset, +// mDataSize, +// mCache->getLocalAPRFilePool()); + S32 bytes_read = (S32)LLFile::read(local_filename, + mReadData, + mOffset, + mDataSize); if (bytes_read != mDataSize) { @@ -410,8 +415,9 @@ bool LLTextureCacheRemoteWorker::doRead() mReadData = (U8*)ll_aligned_malloc_16(size); if (mReadData) { - S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, - mReadData, offset, size, mCache->getLocalAPRFilePool()); +// S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, +// mReadData, offset, size, mCache->getLocalAPRFilePool()); + S32 bytes_read = (S32)LLFile::read(mCache->mHeaderDataFileName, mReadData, offset, size); if (bytes_read != size) { LL_WARNS() << "LLTextureCacheWorker: " << mID @@ -487,10 +493,13 @@ bool LLTextureCacheRemoteWorker::doRead() mReadData = data; // Read the data at last - S32 bytes_read = LLAPRFile::readEx(filename, - mReadData + data_offset, - file_offset, file_size, - mCache->getLocalAPRFilePool()); +// S32 bytes_read = LLAPRFile::readEx(filename, +// mReadData + data_offset, +// file_offset, file_size, +// mCache->getLocalAPRFilePool()); + S32 bytes_read = (S32)LLFile::read(filename, + mReadData + data_offset, + file_offset, file_size); if (bytes_read != file_size) { LL_WARNS() << "LLTextureCacheWorker: " << mID @@ -636,13 +645,15 @@ bool LLTextureCacheRemoteWorker::doWrite() U8* padBuffer = (U8*)ll_aligned_malloc_16(TEXTURE_CACHE_ENTRY_SIZE); memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer - bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool()); +// bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool()); + bytes_written = (S32)LLFile::write(mCache->mHeaderDataFileName, padBuffer, offset, size); ll_aligned_free_16(padBuffer); } else { // Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file - bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool()); +// bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, , mCache->getLocalAPRFilePool()); + bytes_written = (S32)LLFile::write(mCache->mHeaderDataFileName, mWriteData, offset, size); } if (bytes_written <= 0) @@ -678,15 +689,15 @@ bool LLTextureCacheRemoteWorker::doWrite() else { S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE; - { // build the cache file name from the UUID std::string filename = mCache->getTextureFileName(mID); // LL_INFOS() << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << LL_ENDL; - S32 bytes_written = LLAPRFile::writeEx(filename, +/* S32 bytes_written = LLAPRFile::writeEx(filename, mWriteData + TEXTURE_CACHE_ENTRY_SIZE, 0, file_size, - mCache->getLocalAPRFilePool()); + mCache->getLocalAPRFilePool()); */ + S32 bytes_written = (S32)LLFile::write(filename, mWriteData + TEXTURE_CACHE_ENTRY_SIZE, 0, file_size); if (bytes_written <= 0) { LL_WARNS() << "LLTextureCacheWorker: " << mID @@ -943,7 +954,7 @@ const char* fast_cache_filename = "FastCache.cache"; void LLTextureCache::setDirNames(ELLPath location) { - std::string delem = gDirUtilp->getDirDelimiter(); +// std::string delem = gDirUtilp->getDirDelimiter(); mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, entries_filename); mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, cache_filename); @@ -1072,8 +1083,9 @@ void LLTextureCache::readEntriesHeader() llassert_always(mHeaderAPRFile == NULL); if (LLFile::isfile(mHeaderEntriesFileName)) { - LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), - mHeaderAPRFilePoolp); +// LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), +// mHeaderAPRFilePoolp); + LLFile::read(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); } else //create an empty entries header. { @@ -1089,7 +1101,7 @@ void LLTextureCache::setEntriesHeader() // For simplicity we use predefined size of header, so if version string // doesn't fit, either getEngineInfo() returned malformed string or // sHeaderEncoderStringSize need to be increased. - // Also take into accout that c_str() returns additional null character + // Also take into account that c_str() returns additional null character LL_ERRS() << "Version string doesn't fit in header" << LL_ENDL; } @@ -1104,8 +1116,9 @@ void LLTextureCache::writeEntriesHeader() llassert_always(mHeaderAPRFile == NULL); if (!mReadOnly) { - LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), - mHeaderAPRFilePoolp); +// LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), +// mHeaderAPRFilePoolp); + LLFile::write(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); } } @@ -1209,8 +1222,7 @@ void LLTextureCache::writeEntryToHeaderImmediately(S32& idx, Entry& entry, bool idx = -1 ;//mark the idx invalid. return ; } - - mHeaderAPRFile->seek(APR_SET, offset); + aprfile->seek(APR_SET, offset); } else { -- cgit v1.3