From 3fc07dea01795b31c37dcd093ec73d190a1e188a Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Wed, 16 Sep 2020 18:53:24 -0700 Subject: First part of change to remove LLVFS from the Viewer. Consists of code changes to remove LLVFS and LLVFSThread classes along with the associated source files. The existing llvfs folder is renamed to llcache. Also includes changes to CMake script in many places to reflect changes. Eventually, llvfile source file and class will be renamed but that is not in this change. --- indra/llui/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index cce618487b..02020b19c6 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -13,7 +13,7 @@ include(LLCoreHttp) include(LLRender) include(LLWindow) include(LLCoreHttp) -include(LLVFS) +include(LLCache) include(LLXML) include_directories( @@ -25,7 +25,7 @@ include_directories( ${LLMESSAGE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} - ${LLVFS_INCLUDE_DIRS} + ${LLCACHE_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${LIBS_PREBUILD_DIR}/include/hunspell ) @@ -283,7 +283,7 @@ target_link_libraries(llui ${LLINVENTORY_LIBRARIES} ${LLMESSAGE_LIBRARIES} ${LLCOREHTTP_LIBRARIES} - ${LLVFS_LIBRARIES} # ugh, just for LLDir + ${LLCACHE_LIBRARIES} # ugh, just for LLDir ${LLXUIXML_LIBRARIES} ${LLXML_LIBRARIES} ${LLMATH_LIBRARIES} -- cgit v1.3 From 2e6f5164116e084fe35f952180c3f7092ad8350f Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Wed, 16 Sep 2020 21:12:53 -0700 Subject: Renamed the references to LLVFile and llvfile.* source code plus cmake scripts to use a different name - lldiskcache - since that more closely resembles what it is (or will be) now that the VFA is no more --- indra/llappearance/lltexlayer.cpp | 2 +- indra/llaudio/llaudiodecodemgr.cpp | 14 +- indra/llaudio/llaudioengine.cpp | 4 +- indra/llcache/CMakeLists.txt | 6 +- indra/llcache/lldiskcache.cpp | 387 ++++++++++++++++++++++++++++++ indra/llcache/lldiskcache.h | 82 +++++++ indra/llcache/llpidlock.cpp | 276 --------------------- indra/llcache/llpidlock.h | 60 ----- indra/llcache/llvfile.cpp | 387 ------------------------------ indra/llcache/llvfile.h | 82 ------- indra/llcharacter/llkeyframemotion.cpp | 6 +- indra/llcrashlogger/llcrashlock.h | 2 +- indra/llmessage/llassetstorage.cpp | 28 +-- indra/llmessage/llcorehttputil.cpp | 4 +- indra/llmessage/lltransfersourceasset.cpp | 6 +- indra/llmessage/lltransfersourceasset.h | 2 +- indra/llmessage/lltransfertargetvfile.cpp | 8 +- indra/llmessage/lltransfertargetvfile.h | 4 +- indra/llmessage/llxfer_vfile.cpp | 22 +- indra/llmessage/llxfer_vfile.h | 4 +- indra/llui/llviewereventrecorder.h | 2 +- indra/newview/llappviewer.cpp | 8 +- indra/newview/llcompilequeue.cpp | 2 +- indra/newview/llfloaterauction.cpp | 6 +- indra/newview/llfloaterbvhpreview.cpp | 4 +- indra/newview/llfloatermodelpreview.cpp | 2 +- indra/newview/llfloaterregioninfo.cpp | 4 +- indra/newview/llfloaterreporter.cpp | 4 +- indra/newview/llfloatertos.cpp | 2 +- indra/newview/llgesturemgr.cpp | 4 +- indra/newview/lllandmarklist.cpp | 4 +- indra/newview/llmeshrepository.cpp | 22 +- indra/newview/lloutfitgallery.cpp | 2 +- indra/newview/llpostcard.cpp | 2 +- indra/newview/llpreviewgesture.cpp | 6 +- indra/newview/llpreviewnotecard.cpp | 10 +- indra/newview/llpreviewscript.cpp | 6 +- indra/newview/llsettingsvo.cpp | 4 +- indra/newview/llsnapshotlivepreview.cpp | 4 +- indra/newview/llviewerassetstorage.cpp | 12 +- indra/newview/llviewerassetstorage.h | 2 +- indra/newview/llviewerassetupload.cpp | 8 +- indra/newview/llviewermenufile.cpp | 2 +- indra/newview/llviewermessage.cpp | 4 +- indra/newview/llviewerstats.cpp | 2 +- indra/newview/llviewertexlayer.cpp | 2 +- indra/newview/llviewertexture.cpp | 2 +- indra/newview/llviewertexture.h | 2 +- indra/newview/llviewertexturelist.cpp | 2 +- 49 files changed, 592 insertions(+), 930 deletions(-) create mode 100644 indra/llcache/lldiskcache.cpp create mode 100644 indra/llcache/lldiskcache.h delete mode 100644 indra/llcache/llpidlock.cpp delete mode 100644 indra/llcache/llpidlock.h delete mode 100644 indra/llcache/llvfile.cpp delete mode 100644 indra/llcache/llvfile.h (limited to 'indra/llui') diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 2a7e5f3ddb..7360c1acd7 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -33,7 +33,7 @@ #include "llimagej2c.h" #include "llimagetga.h" #include "lldir.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "lltexlayerparams.h" #include "lltexturemanagerbridge.h" #include "lllocaltextureobject.h" diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index d2c4163280..fcffea42a4 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -29,7 +29,7 @@ #include "llaudioengine.h" #include "lllfsthread.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llstring.h" #include "lldir.h" #include "llendianswizzle.h" @@ -93,14 +93,14 @@ protected: std::string mOutFilename; LLLFSThread::handle_t mFileHandle; - LLVFile *mInFilep; + LLDiskCache *mInFilep; OggVorbis_File mVF; S32 mCurrentSection; }; size_t cache_read(void *ptr, size_t size, size_t nmemb, void *datasource) { - LLVFile *file = (LLVFile *)datasource; + LLDiskCache *file = (LLDiskCache *)datasource; if (file->read((U8*)ptr, (S32)(size * nmemb))) /*Flawfinder: ignore*/ { @@ -115,7 +115,7 @@ size_t cache_read(void *ptr, size_t size, size_t nmemb, void *datasource) S32 cache_seek(void *datasource, ogg_int64_t offset, S32 whence) { - LLVFile *file = (LLVFile *)datasource; + LLDiskCache *file = (LLDiskCache *)datasource; // cache has 31-bit files if (offset > S32_MAX) @@ -151,14 +151,14 @@ S32 cache_seek(void *datasource, ogg_int64_t offset, S32 whence) S32 cache_close (void *datasource) { - LLVFile *file = (LLVFile *)datasource; + LLDiskCache *file = (LLDiskCache *)datasource; delete file; return 0; } long cache_tell (void *datasource) { - LLVFile *file = (LLVFile *)datasource; + LLDiskCache *file = (LLDiskCache *)datasource; return file->tell(); } @@ -198,7 +198,7 @@ BOOL LLVorbisDecodeState::initDecode() LL_DEBUGS("AudioEngine") << "Initing decode from vfile: " << mUUID << LL_ENDL; - mInFilep = new LLVFile(mUUID, LLAssetType::AT_SOUND); + mInFilep = new LLDiskCache(mUUID, LLAssetType::AT_SOUND); if (!mInFilep || !mInFilep->getSize()) { LL_WARNS("AudioEngine") << "unable to open vorbis source vfile for reading" << LL_ENDL; diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 9c8bd3225b..9dd752f492 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -35,7 +35,7 @@ #include "sound_ids.h" // temporary hack for min/max distances -#include "llvfile.h" +#include "lldiskcache.h" #include "lldir.h" #include "llaudiodecodemgr.h" #include "llassetstorage.h" @@ -1015,7 +1015,7 @@ bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid) bool LLAudioEngine::hasLocalFile(const LLUUID &uuid) { // See if it's in the cache. - bool have_local = LLVFile::getExists(uuid, LLAssetType::AT_SOUND); + bool have_local = LLDiskCache::getExists(uuid, LLAssetType::AT_SOUND); LL_DEBUGS("AudioEngine") << "sound uuid " << uuid << " exists in cache" << LL_ENDL; return have_local; } diff --git a/indra/llcache/CMakeLists.txt b/indra/llcache/CMakeLists.txt index ab84bd96a0..379e3ebdbf 100644 --- a/indra/llcache/CMakeLists.txt +++ b/indra/llcache/CMakeLists.txt @@ -15,8 +15,7 @@ set(llcache_SOURCE_FILES lldir.cpp lldiriterator.cpp lllfsthread.cpp - llpidlock.cpp - llvfile.cpp + lldiskcache.cpp ) set(llcache_HEADER_FILES @@ -26,8 +25,7 @@ set(llcache_HEADER_FILES lldirguard.h lldiriterator.h lllfsthread.h - llpidlock.h - llvfile.h + lldiskcache.h ) if (DARWIN) diff --git a/indra/llcache/lldiskcache.cpp b/indra/llcache/lldiskcache.cpp new file mode 100644 index 0000000000..af93049e07 --- /dev/null +++ b/indra/llcache/lldiskcache.cpp @@ -0,0 +1,387 @@ +/** + * @file lldiskcache.cpp + * @brief Implementation of virtual file + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lldiskcache.h" + +#include "llerror.h" +#include "llthread.h" +#include "lltimer.h" +#include "llfasttimer.h" +#include "llmemory.h" + +#include +#include "lldir.h" + +const S32 LLDiskCache::READ = 0x00000001; +const S32 LLDiskCache::WRITE = 0x00000002; +const S32 LLDiskCache::READ_WRITE = 0x00000003; // LLDiskCache::READ & LLDiskCache::WRITE +const S32 LLDiskCache::APPEND = 0x00000006; // 0x00000004 & LLDiskCache::WRITE + +static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait"); + +LLDiskCache::LLDiskCache(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode) +{ + mFileType = file_type; + mFileID = file_id; + mPosition = 0; + mBytesRead = 0; + mReadComplete = FALSE; + mMode = mode; +} + +LLDiskCache::~LLDiskCache() +{ +} + +const std::string assetTypeToString(LLAssetType::EType at) +{ + /** + * Make use of the C++17 (or is it 14) feature that allows + * for inline initialization of an std::map<> + */ + typedef std::map asset_type_to_name_t; + asset_type_to_name_t asset_type_to_name = + { + { LLAssetType::AT_TEXTURE, "TEXTURE" }, + { LLAssetType::AT_SOUND, "SOUND" }, + { LLAssetType::AT_CALLINGCARD, "CALLINGCARD" }, + { LLAssetType::AT_LANDMARK, "LANDMARK" }, + { LLAssetType::AT_SCRIPT, "SCRIPT" }, + { LLAssetType::AT_CLOTHING, "CLOTHING" }, + { LLAssetType::AT_OBJECT, "OBJECT" }, + { LLAssetType::AT_NOTECARD, "NOTECARD" }, + { LLAssetType::AT_CATEGORY, "CATEGORY" }, + { LLAssetType::AT_LSL_TEXT, "LSL_TEXT" }, + { LLAssetType::AT_LSL_BYTECODE, "LSL_BYTECODE" }, + { LLAssetType::AT_TEXTURE_TGA, "TEXTURE_TGA" }, + { LLAssetType::AT_BODYPART, "BODYPART" }, + { LLAssetType::AT_SOUND_WAV, "SOUND_WAV" }, + { LLAssetType::AT_IMAGE_TGA, "IMAGE_TGA" }, + { LLAssetType::AT_IMAGE_JPEG, "IMAGE_JPEG" }, + { LLAssetType::AT_ANIMATION, "ANIMATION" }, + { LLAssetType::AT_GESTURE, "GESTURE" }, + { LLAssetType::AT_SIMSTATE, "SIMSTATE" }, + { LLAssetType::AT_LINK, "LINK" }, + { LLAssetType::AT_LINK_FOLDER, "LINK_FOLDER" }, + { LLAssetType::AT_MARKETPLACE_FOLDER, "MARKETPLACE_FOLDER" }, + { LLAssetType::AT_WIDGET, "WIDGET" }, + { LLAssetType::AT_PERSON, "PERSON" }, + { LLAssetType::AT_MESH, "MESH" }, + { LLAssetType::AT_SETTINGS, "SETTINGS" }, + { LLAssetType::AT_UNKNOWN, "UNKNOWN" } + }; + + asset_type_to_name_t::iterator iter = asset_type_to_name.find(at); + if (iter != asset_type_to_name.end()) + { + return iter->second; + } + + return std::string("UNKNOWN"); +} + +const std::string idToFilepath(const std::string id, LLAssetType::EType at) +{ + /** + * For the moment this is just {UUID}_{ASSET_TYPE}.txt but of + * course, will be greatly expanded upon + */ + std::ostringstream ss; + ss << "00cache_"; + ss << id; + ss << "_"; + ss << assetTypeToString(at); + ss << ".txt"; + + const std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ss.str()); + + return filepath; +} + +// static +bool LLDiskCache::getExists(const LLUUID &file_id, const LLAssetType::EType file_type) +{ + std::string id_str; + file_id.toString(id_str); + const std::string filename = idToFilepath(id_str, file_type); + + std::ifstream file(filename, std::ios::binary); + if (file.is_open()) + { + file.seekg(0, std::ios::end); + return file.tellg() > 0; + } + return false; +} + +// static +bool LLDiskCache::removeFile(const LLUUID &file_id, const LLAssetType::EType file_type) +{ + std::string id_str; + file_id.toString(id_str); + const std::string filename = idToFilepath(id_str, file_type); + + std::remove(filename.c_str()); + + return true; +} + +// static +bool LLDiskCache::renameFile(const LLUUID &old_file_id, const LLAssetType::EType old_file_type, + const LLUUID &new_file_id, const LLAssetType::EType new_file_type) +{ + std::string old_id_str; + old_file_id.toString(old_id_str); + const std::string old_filename = idToFilepath(old_id_str, old_file_type); + + std::string new_id_str; + new_file_id.toString(new_id_str); + const std::string new_filename = idToFilepath(new_id_str, new_file_type); + + if (std::rename(old_filename.c_str(), new_filename.c_str())) + { + // We would like to return FALSE here indicating the operation + // failed but the original code does not and doing so seems to + // break a lot of things so we go with the flow... + //return FALSE; + } + + return TRUE; +} + +// static +S32 LLDiskCache::getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type) +{ + std::string id_str; + file_id.toString(id_str); + const std::string filename = idToFilepath(id_str, file_type); + + S32 file_size = 0; + std::ifstream file(filename, std::ios::binary); + if (file.is_open()) + { + file.seekg(0, std::ios::end); + file_size = file.tellg(); + } + + return file_size; +} + +BOOL LLDiskCache::read(U8 *buffer, S32 bytes, BOOL async, F32 priority) +{ + BOOL success = TRUE; + + mReadComplete = FALSE; + + std::string id; + mFileID.toString(id); + const std::string filename = idToFilepath(id, mFileType); + + std::ifstream file(filename, std::ios::binary); + if (file.is_open()) + { + file.seekg(mPosition, std::ios::beg); + + file.read((char*)buffer, bytes); + + if (file) + { + mBytesRead = bytes; + } + else + { + mBytesRead = file.gcount(); + } + + file.close(); + + mPosition += mBytesRead; + if (!mBytesRead) + { + success = FALSE; + } + + mReadComplete = TRUE; + } + + return success; +} + +BOOL LLDiskCache::isReadComplete() +{ + if (mReadComplete) + { + return TRUE; + } + + return FALSE; +} + +S32 LLDiskCache::getLastBytesRead() +{ + return mBytesRead; +} + +BOOL LLDiskCache::eof() +{ + return mPosition >= getSize(); +} + +BOOL LLDiskCache::write(const U8 *buffer, S32 bytes) +{ + std::string id_str; + mFileID.toString(id_str); + const std::string filename = idToFilepath(id_str, mFileType); + + BOOL success = FALSE; + + if (mMode == APPEND) + { + std::ofstream ofs(filename, std::ios::app | std::ios::binary); + if (ofs) + { + ofs.write((const char*)buffer, bytes); + + success = TRUE; + } + } + else + { + std::ofstream ofs(filename, std::ios::binary); + if (ofs) + { + ofs.write((const char*)buffer, bytes); + + mPosition += bytes; + + success = TRUE; + } + } + + return success; +} + +//static +BOOL LLDiskCache::writeFile(const U8 *buffer, S32 bytes, const LLUUID &uuid, LLAssetType::EType type) +{ + LLDiskCache file(uuid, type, LLDiskCache::WRITE); + file.setMaxSize(bytes); + return file.write(buffer, bytes); +} + +BOOL LLDiskCache::seek(S32 offset, S32 origin) +{ + if (-1 == origin) + { + origin = mPosition; + } + + S32 new_pos = origin + offset; + + S32 size = getSize(); + + if (new_pos > size) + { + LL_WARNS() << "Attempt to seek past end of file" << LL_ENDL; + + mPosition = size; + return FALSE; + } + else if (new_pos < 0) + { + LL_WARNS() << "Attempt to seek past beginning of file" << LL_ENDL; + + mPosition = 0; + return FALSE; + } + + mPosition = new_pos; + return TRUE; +} + +S32 LLDiskCache::tell() const +{ + return mPosition; +} + +S32 LLDiskCache::getSize() +{ + return LLDiskCache::getFileSize(mFileID, mFileType); +} + +S32 LLDiskCache::getMaxSize() +{ + // offer up a huge size since we don't care what the max is + return INT_MAX; +} + +BOOL LLDiskCache::setMaxSize(S32 size) +{ + // we don't care what the max size is so we do nothing + // and return true to indicate all was okay + return TRUE; +} + +BOOL LLDiskCache::rename(const LLUUID &new_id, const LLAssetType::EType new_type) +{ + LLDiskCache::renameFile(mFileID, mFileType, new_id, new_type); + + mFileID = new_id; + mFileType = new_type; + + return TRUE; +} + +BOOL LLDiskCache::remove() +{ + LLDiskCache::removeFile(mFileID, mFileType); + + return TRUE; +} + +// static +void LLDiskCache::initClass() +{ +} + +// static +void LLDiskCache::cleanupClass() +{ +} + +bool LLDiskCache::isLocked() +{ + // I don't think we care about this test since there is no locking + // TODO: remove this function and calling sites? + return FALSE; +} + +void LLDiskCache::waitForLock() +{ + // TODO: remove this function and calling sites? +} diff --git a/indra/llcache/lldiskcache.h b/indra/llcache/lldiskcache.h new file mode 100644 index 0000000000..7ad06a8689 --- /dev/null +++ b/indra/llcache/lldiskcache.h @@ -0,0 +1,82 @@ +/** + * @file lldiskcacke.h + * @brief Definition of virtual file + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDISKCACHE_H +#define LL_LLDISKCACHE_H + +#include "lluuid.h" +#include "llassettype.h" + +class LLDiskCache +{ +public: + LLDiskCache(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode = LLDiskCache::READ); + ~LLDiskCache(); + + BOOL read(U8 *buffer, S32 bytes, BOOL async = FALSE, F32 priority = 128.f); /* Flawfinder: ignore */ + BOOL isReadComplete(); + S32 getLastBytesRead(); + BOOL eof(); + + BOOL write(const U8 *buffer, S32 bytes); + static BOOL writeFile(const U8 *buffer, S32 bytes, const LLUUID &uuid, LLAssetType::EType type); + BOOL seek(S32 offset, S32 origin = -1); + S32 tell() const; + + S32 getSize(); + S32 getMaxSize(); + BOOL setMaxSize(S32 size); + BOOL rename(const LLUUID &new_id, const LLAssetType::EType new_type); + BOOL remove(); + + bool isLocked(); + void waitForLock(); + + static bool getExists(const LLUUID &file_id, const LLAssetType::EType file_type); + static bool removeFile(const LLUUID &file_id, const LLAssetType::EType file_type); + 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 S32 getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type); + + static void initClass(); + static void cleanupClass(); + +public: + static const S32 READ; + static const S32 WRITE; + static const S32 READ_WRITE; + static const S32 APPEND; + +protected: + LLAssetType::EType mFileType; + BOOL mReadComplete; + LLUUID mFileID; + S32 mPosition; + S32 mMode; + S32 mBytesRead; +}; + +#endif // LL_LLDISKCACHE_H diff --git a/indra/llcache/llpidlock.cpp b/indra/llcache/llpidlock.cpp deleted file mode 100644 index f770e93d45..0000000000 --- a/indra/llcache/llpidlock.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/** - * @file llformat.cpp - * @date January 2007 - * @brief string formatting utility - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llapr.h" // thread-related functions -#include "llpidlock.h" -#include "lldir.h" -#include "llsd.h" -#include "llsdserialize.h" -#include "llnametable.h" -#include "llframetimer.h" - -#if LL_WINDOWS //For windows platform. - -#include - -bool isProcessAlive(U32 pid) -{ - return (bool) GetProcessVersion((DWORD)pid); -} - -#else //Everyone Else -bool isProcessAlive(U32 pid) -{ - return (bool) kill( (pid_t)pid, 0); -} -#endif //Everyone else. - - - -class LLPidLockFile -{ - public: - LLPidLockFile( ) : - mAutosave(false), - mSaving(false), - mWaiting(false), - mPID(getpid()), - mNameTable(NULL), - mClean(true) - { - mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock"; - } - bool requestLock(LLNameTable *name_table, bool autosave, - bool force_immediate=FALSE, F32 timeout=300.0); - bool checkLock(); - void releaseLock(); - - private: - void writeLockFile(LLSD pids); - public: - static LLPidLockFile& instance(); // return the singleton black list file - - bool mAutosave; - bool mSaving; - bool mWaiting; - LLFrameTimer mTimer; - U32 mPID; - std::string mLockName; - std::string mSaveName; - LLSD mPIDS_sd; - LLNameTable *mNameTable; - bool mClean; -}; - -LLPidLockFile& LLPidLockFile::instance() -{ - static LLPidLockFile the_file; - return the_file; -} - -void LLPidLockFile::writeLockFile(LLSD pids) -{ - llofstream ofile(mLockName.c_str()); - - if (!LLSDSerialize::toXML(pids,ofile)) - { - LL_WARNS() << "Unable to write concurrent save lock file." << LL_ENDL; - } - ofile.close(); -} - -bool LLPidLockFile::requestLock(LLNameTable *name_table, bool autosave, - bool force_immediate, F32 timeout) -{ - bool readyToSave = FALSE; - - if (mSaving) return FALSE; //Bail out if we're currently saving. Will not queue another save. - - if (!mWaiting){ - mNameTable=name_table; - mAutosave = autosave; - } - - LLSD out_pids; - out_pids.append( (LLSD::Integer)mPID ); - - llifstream ifile(mLockName.c_str()); - - if (ifile.is_open()) - { //If file exists, we need to decide whether or not to continue. - if ( force_immediate - || mTimer.hasExpired() ) //Only deserialize if we REALLY need to. - { - - LLSD in_pids; - - LLSDSerialize::fromXML(in_pids, ifile); - - //Clean up any dead PIDS that might be in there. - for (LLSD::array_iterator i=in_pids.beginArray(); - i !=in_pids.endArray(); - ++i) - { - U32 stored_pid=(*i).asInteger(); - - if (isProcessAlive(stored_pid)) - { - out_pids.append( (*i) ); - } - } - - readyToSave=TRUE; - } - ifile.close(); - } - else - { - readyToSave=TRUE; - } - - if (!mWaiting) //Not presently waiting to save. Queue up. - { - mTimer.resetWithExpiry(timeout); - mWaiting=TRUE; - } - - if (readyToSave) - { //Potential race condition won't kill us. Ignore it. - writeLockFile(out_pids); - mSaving=TRUE; - } - - return readyToSave; -} - -bool LLPidLockFile::checkLock() -{ - return mWaiting; -} - -void LLPidLockFile::releaseLock() -{ - llifstream ifile(mLockName.c_str()); - LLSD in_pids; - LLSD out_pids; - bool write_file=FALSE; - - LLSDSerialize::fromXML(in_pids, ifile); - - //Clean up this PID and any dead ones. - for (LLSD::array_iterator i=in_pids.beginArray(); - i !=in_pids.endArray(); - ++i) - { - U32 stored_pid=(*i).asInteger(); - - if (stored_pid != mPID && isProcessAlive(stored_pid)) - { - out_pids.append( (*i) ); - write_file=TRUE; - } - } - ifile.close(); - - if (write_file) - { - writeLockFile(out_pids); - } - else - { - unlink(mLockName.c_str()); - } - - mSaving=FALSE; - mWaiting=FALSE; -} - -//LLPidLock - -void LLPidLock::initClass() { - (void) LLPidLockFile::instance(); -} - -bool LLPidLock::checkLock() -{ - return LLPidLockFile::instance().checkLock(); -} - -bool LLPidLock::requestLock(LLNameTable *name_table, bool autosave, - bool force_immediate, F32 timeout) -{ - return LLPidLockFile::instance().requestLock(name_table,autosave,force_immediate,timeout); -} - -void LLPidLock::releaseLock() -{ - return LLPidLockFile::instance().releaseLock(); -} - -bool LLPidLock::isClean() -{ - return LLPidLockFile::instance().mClean; -} - -//getters -LLNameTable * LLPidLock::getNameTable() -{ - return LLPidLockFile::instance().mNameTable; -} - -bool LLPidLock::getAutosave() -{ - return LLPidLockFile::instance().mAutosave; -} - -bool LLPidLock::getClean() -{ - return LLPidLockFile::instance().mClean; -} - -std::string LLPidLock::getSaveName() -{ - return LLPidLockFile::instance().mSaveName; -} - -//setters -void LLPidLock::setClean(bool clean) -{ - LLPidLockFile::instance().mClean=clean; -} - -void LLPidLock::setSaveName(std::string savename) -{ - LLPidLockFile::instance().mSaveName=savename; -} - -S32 LLPidLock::getPID() -{ - return (S32)getpid(); -} diff --git a/indra/llcache/llpidlock.h b/indra/llcache/llpidlock.h deleted file mode 100644 index 334f26bb29..0000000000 --- a/indra/llcache/llpidlock.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file llpidlock.h - * @brief System information debugging classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_PIDLOCK_H -#define LL_PIDLOCK_H -#include "llnametable.h" - -class LLSD; -class LLFrameTimer; - -#if !LL_WINDOWS //For non-windows platforms. -#include -#endif - -namespace LLPidLock -{ - void initClass(); // { (void) LLPidLockFile::instance(); } - - bool requestLock( LLNameTable *name_table=NULL, bool autosave=TRUE, - bool force_immediate=FALSE, F32 timeout=300.0); - bool checkLock(); - void releaseLock(); - bool isClean(); - - //getters - LLNameTable * getNameTable(); - bool getAutosave(); - bool getClean(); - std::string getSaveName(); - S32 getPID(); - - //setters - void setClean(bool clean); - void setSaveName(std::string savename); -}; - -#endif // LL_PIDLOCK_H diff --git a/indra/llcache/llvfile.cpp b/indra/llcache/llvfile.cpp deleted file mode 100644 index be753244c0..0000000000 --- a/indra/llcache/llvfile.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/** - * @file llvfile.cpp - * @brief Implementation of virtual file - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llvfile.h" - -#include "llerror.h" -#include "llthread.h" -#include "lltimer.h" -#include "llfasttimer.h" -#include "llmemory.h" - -#include -#include "lldir.h" - -const S32 LLVFile::READ = 0x00000001; -const S32 LLVFile::WRITE = 0x00000002; -const S32 LLVFile::READ_WRITE = 0x00000003; // LLVFile::READ & LLVFile::WRITE -const S32 LLVFile::APPEND = 0x00000006; // 0x00000004 & LLVFile::WRITE - -static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait"); - -LLVFile::LLVFile(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode) -{ - mFileType = file_type; - mFileID = file_id; - mPosition = 0; - mBytesRead = 0; - mReadComplete = FALSE; - mMode = mode; -} - -LLVFile::~LLVFile() -{ -} - -const std::string assetTypeToString(LLAssetType::EType at) -{ - /** - * Make use of the C++17 (or is it 14) feature that allows - * for inline initialization of an std::map<> - */ - typedef std::map asset_type_to_name_t; - asset_type_to_name_t asset_type_to_name = - { - { LLAssetType::AT_TEXTURE, "TEXTURE" }, - { LLAssetType::AT_SOUND, "SOUND" }, - { LLAssetType::AT_CALLINGCARD, "CALLINGCARD" }, - { LLAssetType::AT_LANDMARK, "LANDMARK" }, - { LLAssetType::AT_SCRIPT, "SCRIPT" }, - { LLAssetType::AT_CLOTHING, "CLOTHING" }, - { LLAssetType::AT_OBJECT, "OBJECT" }, - { LLAssetType::AT_NOTECARD, "NOTECARD" }, - { LLAssetType::AT_CATEGORY, "CATEGORY" }, - { LLAssetType::AT_LSL_TEXT, "LSL_TEXT" }, - { LLAssetType::AT_LSL_BYTECODE, "LSL_BYTECODE" }, - { LLAssetType::AT_TEXTURE_TGA, "TEXTURE_TGA" }, - { LLAssetType::AT_BODYPART, "BODYPART" }, - { LLAssetType::AT_SOUND_WAV, "SOUND_WAV" }, - { LLAssetType::AT_IMAGE_TGA, "IMAGE_TGA" }, - { LLAssetType::AT_IMAGE_JPEG, "IMAGE_JPEG" }, - { LLAssetType::AT_ANIMATION, "ANIMATION" }, - { LLAssetType::AT_GESTURE, "GESTURE" }, - { LLAssetType::AT_SIMSTATE, "SIMSTATE" }, - { LLAssetType::AT_LINK, "LINK" }, - { LLAssetType::AT_LINK_FOLDER, "LINK_FOLDER" }, - { LLAssetType::AT_MARKETPLACE_FOLDER, "MARKETPLACE_FOLDER" }, - { LLAssetType::AT_WIDGET, "WIDGET" }, - { LLAssetType::AT_PERSON, "PERSON" }, - { LLAssetType::AT_MESH, "MESH" }, - { LLAssetType::AT_SETTINGS, "SETTINGS" }, - { LLAssetType::AT_UNKNOWN, "UNKNOWN" } - }; - - asset_type_to_name_t::iterator iter = asset_type_to_name.find(at); - if (iter != asset_type_to_name.end()) - { - return iter->second; - } - - return std::string("UNKNOWN"); -} - -const std::string idToFilepath(const std::string id, LLAssetType::EType at) -{ - /** - * For the moment this is just {UUID}_{ASSET_TYPE}.txt but of - * course, will be greatly expanded upon - */ - std::ostringstream ss; - ss << "00cache_"; - ss << id; - ss << "_"; - ss << assetTypeToString(at); - ss << ".txt"; - - const std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ss.str()); - - return filepath; -} - -// static -bool LLVFile::getExists(const LLUUID &file_id, const LLAssetType::EType file_type) -{ - std::string id_str; - file_id.toString(id_str); - const std::string filename = idToFilepath(id_str, file_type); - - std::ifstream file(filename, std::ios::binary); - if (file.is_open()) - { - file.seekg(0, std::ios::end); - return file.tellg() > 0; - } - return false; -} - -// static -bool LLVFile::removeFile(const LLUUID &file_id, const LLAssetType::EType file_type) -{ - std::string id_str; - file_id.toString(id_str); - const std::string filename = idToFilepath(id_str, file_type); - - std::remove(filename.c_str()); - - return true; -} - -// static -bool LLVFile::renameFile(const LLUUID &old_file_id, const LLAssetType::EType old_file_type, - const LLUUID &new_file_id, const LLAssetType::EType new_file_type) -{ - std::string old_id_str; - old_file_id.toString(old_id_str); - const std::string old_filename = idToFilepath(old_id_str, old_file_type); - - std::string new_id_str; - new_file_id.toString(new_id_str); - const std::string new_filename = idToFilepath(new_id_str, new_file_type); - - if (std::rename(old_filename.c_str(), new_filename.c_str())) - { - // We would like to return FALSE here indicating the operation - // failed but the original code does not and doing so seems to - // break a lot of things so we go with the flow... - //return FALSE; - } - - return TRUE; -} - -// static -S32 LLVFile::getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type) -{ - std::string id_str; - file_id.toString(id_str); - const std::string filename = idToFilepath(id_str, file_type); - - S32 file_size = 0; - std::ifstream file(filename, std::ios::binary); - if (file.is_open()) - { - file.seekg(0, std::ios::end); - file_size = file.tellg(); - } - - return file_size; -} - -BOOL LLVFile::read(U8 *buffer, S32 bytes, BOOL async, F32 priority) -{ - BOOL success = TRUE; - - mReadComplete = FALSE; - - std::string id; - mFileID.toString(id); - const std::string filename = idToFilepath(id, mFileType); - - std::ifstream file(filename, std::ios::binary); - if (file.is_open()) - { - file.seekg(mPosition, std::ios::beg); - - file.read((char*)buffer, bytes); - - if (file) - { - mBytesRead = bytes; - } - else - { - mBytesRead = file.gcount(); - } - - file.close(); - - mPosition += mBytesRead; - if (!mBytesRead) - { - success = FALSE; - } - - mReadComplete = TRUE; - } - - return success; -} - -BOOL LLVFile::isReadComplete() -{ - if (mReadComplete) - { - return TRUE; - } - - return FALSE; -} - -S32 LLVFile::getLastBytesRead() -{ - return mBytesRead; -} - -BOOL LLVFile::eof() -{ - return mPosition >= getSize(); -} - -BOOL LLVFile::write(const U8 *buffer, S32 bytes) -{ - std::string id_str; - mFileID.toString(id_str); - const std::string filename = idToFilepath(id_str, mFileType); - - BOOL success = FALSE; - - if (mMode == APPEND) - { - std::ofstream ofs(filename, std::ios::app | std::ios::binary); - if (ofs) - { - ofs.write((const char*)buffer, bytes); - - success = TRUE; - } - } - else - { - std::ofstream ofs(filename, std::ios::binary); - if (ofs) - { - ofs.write((const char*)buffer, bytes); - - mPosition += bytes; - - success = TRUE; - } - } - - return success; -} - -//static -BOOL LLVFile::writeFile(const U8 *buffer, S32 bytes, const LLUUID &uuid, LLAssetType::EType type) -{ - LLVFile file(uuid, type, LLVFile::WRITE); - file.setMaxSize(bytes); - return file.write(buffer, bytes); -} - -BOOL LLVFile::seek(S32 offset, S32 origin) -{ - if (-1 == origin) - { - origin = mPosition; - } - - S32 new_pos = origin + offset; - - S32 size = getSize(); - - if (new_pos > size) - { - LL_WARNS() << "Attempt to seek past end of file" << LL_ENDL; - - mPosition = size; - return FALSE; - } - else if (new_pos < 0) - { - LL_WARNS() << "Attempt to seek past beginning of file" << LL_ENDL; - - mPosition = 0; - return FALSE; - } - - mPosition = new_pos; - return TRUE; -} - -S32 LLVFile::tell() const -{ - return mPosition; -} - -S32 LLVFile::getSize() -{ - return LLVFile::getFileSize(mFileID, mFileType); -} - -S32 LLVFile::getMaxSize() -{ - // offer up a huge size since we don't care what the max is - return INT_MAX; -} - -BOOL LLVFile::setMaxSize(S32 size) -{ - // we don't care what the max size is so we do nothing - // and return true to indicate all was okay - return TRUE; -} - -BOOL LLVFile::rename(const LLUUID &new_id, const LLAssetType::EType new_type) -{ - LLVFile::renameFile(mFileID, mFileType, new_id, new_type); - - mFileID = new_id; - mFileType = new_type; - - return TRUE; -} - -BOOL LLVFile::remove() -{ - LLVFile::removeFile(mFileID, mFileType); - - return TRUE; -} - -// static -void LLVFile::initClass() -{ -} - -// static -void LLVFile::cleanupClass() -{ -} - -bool LLVFile::isLocked() -{ - // I don't think we care about this test since there is no locking - // TODO: remove this function and calling sites? - return FALSE; -} - -void LLVFile::waitForLock() -{ - // TODO: remove this function and calling sites? -} diff --git a/indra/llcache/llvfile.h b/indra/llcache/llvfile.h deleted file mode 100644 index 30130df340..0000000000 --- a/indra/llcache/llvfile.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file llvfile.h - * @brief Definition of virtual file - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLVFILE_H -#define LL_LLVFILE_H - -#include "lluuid.h" -#include "llassettype.h" - -class LLVFile -{ -public: - LLVFile(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode = LLVFile::READ); - ~LLVFile(); - - BOOL read(U8 *buffer, S32 bytes, BOOL async = FALSE, F32 priority = 128.f); /* Flawfinder: ignore */ - BOOL isReadComplete(); - S32 getLastBytesRead(); - BOOL eof(); - - BOOL write(const U8 *buffer, S32 bytes); - static BOOL writeFile(const U8 *buffer, S32 bytes, const LLUUID &uuid, LLAssetType::EType type); - BOOL seek(S32 offset, S32 origin = -1); - S32 tell() const; - - S32 getSize(); - S32 getMaxSize(); - BOOL setMaxSize(S32 size); - BOOL rename(const LLUUID &new_id, const LLAssetType::EType new_type); - BOOL remove(); - - bool isLocked(); - void waitForLock(); - - static bool getExists(const LLUUID &file_id, const LLAssetType::EType file_type); - static bool removeFile(const LLUUID &file_id, const LLAssetType::EType file_type); - 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 S32 getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type); - - static void initClass(); - static void cleanupClass(); - -public: - static const S32 READ; - static const S32 WRITE; - static const S32 READ_WRITE; - static const S32 APPEND; - -protected: - LLAssetType::EType mFileType; - BOOL mReadComplete; - LLUUID mFileID; - S32 mPosition; - S32 mMode; - S32 mBytesRead; -}; - -#endif diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index beca1af269..d1ac336fc1 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -39,7 +39,7 @@ #include "llendianswizzle.h" #include "llkeyframemotion.h" #include "llquantize.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "m3math.h" #include "message.h" @@ -559,7 +559,7 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact S32 anim_file_size; BOOL success = FALSE; - LLVFile* anim_file = new LLVFile(mID, LLAssetType::AT_ANIMATION); + LLDiskCache* anim_file = new LLDiskCache(mID, LLAssetType::AT_ANIMATION); if (!anim_file || !anim_file->getSize()) { delete anim_file; @@ -2324,7 +2324,7 @@ void LLKeyframeMotion::onLoadComplete(const LLUUID& asset_uuid, // asset already loaded return; } - LLVFile file(asset_uuid, type, LLVFile::READ); + LLDiskCache file(asset_uuid, type, LLDiskCache::READ); S32 size = file.getSize(); U8* buffer = new U8[size]; diff --git a/indra/llcrashlogger/llcrashlock.h b/indra/llcrashlogger/llcrashlock.h index cde183272f..60b060b736 100644 --- a/indra/llcrashlogger/llcrashlock.h +++ b/indra/llcrashlogger/llcrashlock.h @@ -1,5 +1,5 @@ /** - * @file llpidlock.h + * @file llcrashlock.h * @brief Maintainence of disk locking files for crash reporting * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index be5d00d4c9..31c1edd75e 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -42,7 +42,7 @@ // this library includes #include "message.h" #include "llxfermanager.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "lldbstrings.h" #include "lltransfersourceasset.h" @@ -438,7 +438,7 @@ void LLAssetStorage::_cleanupRequests(BOOL all, S32 error) BOOL LLAssetStorage::hasLocalAsset(const LLUUID &uuid, const LLAssetType::EType type) { - return LLVFile::getExists(uuid, type); + return LLDiskCache::getExists(uuid, type); } bool LLAssetStorage::findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type, @@ -450,10 +450,10 @@ bool LLAssetStorage::findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetTyp llassert(callback != NULL); } - BOOL exists = LLVFile::getExists(uuid, type); + BOOL exists = LLDiskCache::getExists(uuid, type); if (exists) { - LLVFile file(uuid, type); + LLDiskCache file(uuid, type); U32 size = file.getSize(); if (size > 0) { @@ -523,8 +523,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, return; } - BOOL exists = LLVFile::getExists(uuid, type); - LLVFile file(uuid, type); + BOOL exists = LLDiskCache::getExists(uuid, type); + LLDiskCache file(uuid, type); U32 size = exists ? file.getSize() : 0; if (size > 0) @@ -664,7 +664,7 @@ void LLAssetStorage::downloadCompleteCallback( if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file - LLVFile vfile(callback_id, callback_type); + LLDiskCache vfile(callback_id, callback_type); if (vfile.getSize() <= 0) { LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset " << callback_id << LL_ENDL; @@ -724,8 +724,8 @@ void LLAssetStorage::getEstateAsset( return; } - BOOL exists = LLVFile::getExists(asset_id, atype); - LLVFile file(asset_id, atype); + BOOL exists = LLDiskCache::getExists(asset_id, atype); + LLDiskCache file(asset_id, atype); U32 size = exists ? file.getSize() : 0; if (size > 0) @@ -818,7 +818,7 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback( if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file - LLVFile vfile(req->getUUID(), req->getAType()); + LLDiskCache vfile(req->getUUID(), req->getAType()); if (vfile.getSize() <= 0) { LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL; @@ -860,8 +860,8 @@ void LLAssetStorage::getInvItemAsset( return; } - exists = LLVFile::getExists(asset_id, atype); - LLVFile file(asset_id, atype); + exists = LLDiskCache::getExists(asset_id, atype); + LLDiskCache file(asset_id, atype); size = exists ? file.getSize() : 0; if(exists && size < 1) { @@ -961,7 +961,7 @@ void LLAssetStorage::downloadInvItemCompleteCallback( if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file - LLVFile vfile(req->getUUID(), req->getType()); + LLDiskCache vfile(req->getUUID(), req->getType()); if (vfile.getSize() <= 0) { LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL; @@ -1396,7 +1396,7 @@ void LLAssetStorage::legacyGetDataCallback(const LLUUID &uuid, if ( !status && !toxic ) { - LLVFile file(uuid, type); + LLDiskCache file(uuid, type); std::string uuid_str; diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index c931a89b5b..376558400c 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -37,7 +37,7 @@ #include "llsdserialize.h" #include "reader.h" // JSON #include "writer.h" // JSON -#include "llvfile.h" +#include "lldiskcache.h" #include "message.h" // for getting the port @@ -784,7 +784,7 @@ LLSD HttpCoroutineAdapter::postFileAndSuspend(LLCore::HttpRequest::ptr_t request // scoping for our streams so that they go away when we no longer need them. { LLCore::BufferArrayStream outs(fileData.get()); - LLVFile vfile(assetId, assetType, LLVFile::READ); + LLDiskCache vfile(assetId, assetType, LLDiskCache::READ); S32 fileSize = vfile.getSize(); U8* fileBuffer; diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp index 0156d1a5ef..7b00a95b00 100644 --- a/indra/llmessage/lltransfersourceasset.cpp +++ b/indra/llmessage/lltransfersourceasset.cpp @@ -32,7 +32,7 @@ #include "message.h" #include "lldatapacker.h" #include "lldir.h" -#include "llvfile.h" +#include "lldiskcache.h" LLTransferSourceAsset::LLTransferSourceAsset(const LLUUID &request_id, const F32 priority) : LLTransferSource(LLTST_ASSET, request_id, priority), @@ -99,7 +99,7 @@ LLTSCode LLTransferSourceAsset::dataCallback(const S32 packet_id, return LLTS_SKIP; } - LLVFile vf(mParams.getAssetID(), mParams.getAssetType(), LLVFile::READ); + LLDiskCache vf(mParams.getAssetID(), mParams.getAssetType(), LLDiskCache::READ); if (!vf.getSize()) { @@ -198,7 +198,7 @@ void LLTransferSourceAsset::responderCallback(const LLUUID& uuid, LLAssetType::E if (LL_ERR_NOERR == result) { // Everything's OK. - LLVFile vf(uuid, type, LLVFile::READ); + LLDiskCache vf(uuid, type, LLDiskCache::READ); tsap->mSize = vf.getSize(); status = LLTS_OK; } diff --git a/indra/llmessage/lltransfersourceasset.h b/indra/llmessage/lltransfersourceasset.h index 2c798d0598..d9055202ec 100644 --- a/indra/llmessage/lltransfersourceasset.h +++ b/indra/llmessage/lltransfersourceasset.h @@ -30,7 +30,7 @@ #include "lltransfermanager.h" #include "llassetstorage.h" -class LLVFile; +class LLDiskCache; class LLTransferSourceParamsAsset : public LLTransferSourceParams { diff --git a/indra/llmessage/lltransfertargetvfile.cpp b/indra/llmessage/lltransfertargetvfile.cpp index f2e0232a05..f4a5e71d08 100644 --- a/indra/llmessage/lltransfertargetvfile.cpp +++ b/indra/llmessage/lltransfertargetvfile.cpp @@ -30,7 +30,7 @@ #include "lldatapacker.h" #include "llerror.h" -#include "llvfile.h" +#include "lldiskcache.h" //static void LLTransferTargetVFile::updateQueue(bool shutdown) @@ -138,7 +138,7 @@ LLTSCode LLTransferTargetVFile::dataCallback(const S32 packet_id, U8 *in_datap, //LL_INFOS() << "LLTransferTargetFile::dataCallback" << LL_ENDL; //LL_INFOS() << "Packet: " << packet_id << LL_ENDL; - LLVFile vf(mTempID, mParams.getAssetType(), LLVFile::APPEND); + LLDiskCache vf(mTempID, mParams.getAssetType(), LLDiskCache::APPEND); if (mNeedsCreate) { vf.setMaxSize(mSize); @@ -176,7 +176,7 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status) case LLTS_DONE: if (!mNeedsCreate) { - LLVFile file(mTempID, mParams.getAssetType(), LLVFile::WRITE); + LLDiskCache file(mTempID, mParams.getAssetType(), LLDiskCache::WRITE); if (!file.rename(mParams.getAssetID(), mParams.getAssetType())) { LL_ERRS() << "LLTransferTargetVFile: rename failed" << LL_ENDL; @@ -195,7 +195,7 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status) { // We're aborting this transfer, we don't want to keep this file. LL_WARNS() << "Aborting vfile transfer for " << mParams.getAssetID() << LL_ENDL; - LLVFile vf(mTempID, mParams.getAssetType(), LLVFile::APPEND); + LLDiskCache vf(mTempID, mParams.getAssetType(), LLDiskCache::APPEND); vf.remove(); } break; diff --git a/indra/llmessage/lltransfertargetvfile.h b/indra/llmessage/lltransfertargetvfile.h index c819c1e2f2..4c1bfe22c5 100644 --- a/indra/llmessage/lltransfertargetvfile.h +++ b/indra/llmessage/lltransfertargetvfile.h @@ -29,9 +29,9 @@ #include "lltransfermanager.h" #include "llassetstorage.h" -#include "llvfile.h" +#include "lldiskcache.h" -class LLVFile; +class LLDiskCache; // Lame, an S32 for now until I figure out the deal with how we want to do // error codes. diff --git a/indra/llmessage/llxfer_vfile.cpp b/indra/llmessage/llxfer_vfile.cpp index 0835970cfc..95629d5fea 100644 --- a/indra/llmessage/llxfer_vfile.cpp +++ b/indra/llmessage/llxfer_vfile.cpp @@ -30,7 +30,7 @@ #include "lluuid.h" #include "llerror.h" #include "llmath.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "lldir.h" // size of chunks read from/written to disk @@ -79,9 +79,9 @@ void LLXfer_VFile::cleanup () if (mTempID.notNull() && mDeleteTempFile) { - if (LLVFile::getExists(mTempID, mType)) + if (LLDiskCache::getExists(mTempID, mType)) { - LLVFile file(mTempID, mType, LLVFile::WRITE); + LLDiskCache file(mTempID, mType, LLDiskCache::WRITE); file.remove(); } else @@ -187,9 +187,9 @@ S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host) delete mVFile; mVFile = NULL; - if(LLVFile::getExists(mLocalID, mType)) + if(LLDiskCache::getExists(mLocalID, mType)) { - mVFile = new LLVFile(mLocalID, mType, LLVFile::READ); + mVFile = new LLDiskCache(mLocalID, mType, LLDiskCache::READ); if (mVFile->getSize() <= 0) { @@ -235,9 +235,9 @@ S32 LLXfer_VFile::reopenFileHandle() if (mVFile == NULL) { - if (LLVFile::getExists(mLocalID, mType)) + if (LLDiskCache::getExists(mLocalID, mType)) { - mVFile = new LLVFile(mLocalID, mType, LLVFile::READ); + mVFile = new LLDiskCache(mLocalID, mType, LLDiskCache::READ); } else { @@ -260,7 +260,7 @@ void LLXfer_VFile::setXferSize (S32 xfer_size) // It would be nice if LLXFers could tell which end of the pipe they were if (! mVFile) { - LLVFile file(mTempID, mType, LLVFile::APPEND); + LLDiskCache file(mTempID, mType, LLDiskCache::APPEND); file.setMaxSize(xfer_size); } } @@ -315,7 +315,7 @@ S32 LLXfer_VFile::flush() S32 retval = 0; if (mBufferLength) { - LLVFile file(mTempID, mType, LLVFile::APPEND); + LLDiskCache file(mTempID, mType, LLDiskCache::APPEND); file.write((U8*)mBuffer, mBufferLength); @@ -335,9 +335,9 @@ S32 LLXfer_VFile::processEOF() if (!mCallbackResult) { - if (LLVFile::getExists(mTempID, mType)) + if (LLDiskCache::getExists(mTempID, mType)) { - LLVFile file(mTempID, mType, LLVFile::WRITE); + LLDiskCache file(mTempID, mType, LLDiskCache::WRITE); if (!file.rename(mLocalID, mType)) { LL_WARNS("Xfer") << "Cache rename of temp file failed: unable to rename " << mTempID << " to " << mLocalID << LL_ENDL; diff --git a/indra/llmessage/llxfer_vfile.h b/indra/llmessage/llxfer_vfile.h index d830c4be96..d6ac6ff818 100644 --- a/indra/llmessage/llxfer_vfile.h +++ b/indra/llmessage/llxfer_vfile.h @@ -30,7 +30,7 @@ #include "llxfer.h" #include "llassetstorage.h" -class LLVFile; +class LLDiskCache; class LLXfer_VFile : public LLXfer { @@ -40,7 +40,7 @@ class LLXfer_VFile : public LLXfer LLUUID mTempID; LLAssetType::EType mType; - LLVFile *mVFile; + LLDiskCache *mVFile; std::string mName; diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h index d1059d55de..fec0f9784f 100644 --- a/indra/llui/llviewereventrecorder.h +++ b/indra/llui/llviewereventrecorder.h @@ -32,7 +32,7 @@ #include "lldir.h" #include "llsd.h" #include "llfile.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "lldate.h" #include "llsdserialize.h" #include "llkeyboard.h" diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b9e3a44786..628a4da921 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -114,7 +114,7 @@ #include "llprimitive.h" #include "llurlaction.h" #include "llurlentry.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llvolumemgr.h" #include "llxfermanager.h" #include "llphysicsextensions.h" @@ -1874,8 +1874,8 @@ bool LLAppViewer::cleanup() SUBSYSTEM_CLEANUP(LLWorldMapView); SUBSYSTEM_CLEANUP(LLFolderViewItem); - LL_INFOS() << "Cleaning up VFILE" << LL_ENDL; - SUBSYSTEM_CLEANUP(LLVFile); + LL_INFOS() << "Cleaning up disk cache" << LL_ENDL; + SUBSYSTEM_CLEANUP(LLDiskCache); LL_INFOS() << "Saving Data" << LL_ENDL; @@ -4148,7 +4148,7 @@ bool LLAppViewer::initCache() LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()); - LLVFile::initClass(); + LLDiskCache::initClass(); return true; } diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 96a2f6796d..5ed8d24bcb 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -52,7 +52,7 @@ #include "lldir.h" #include "llnotificationsutil.h" #include "llviewerstats.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "lluictrlfactory.h" #include "lltrans.h" diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index bbb6409111..42bcb86454 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -32,7 +32,7 @@ #include "llimagej2c.h" #include "llimagetga.h" #include "llparcel.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llwindow.h" #include "message.h" @@ -201,7 +201,7 @@ void LLFloaterAuction::onClickSnapshot(void* data) LLPointer tga = new LLImageTGA; tga->encode(raw); - LLVFile::writeFile(tga->getData(), tga->getDataSize(), self->mImageID, LLAssetType::AT_IMAGE_TGA); + LLDiskCache::writeFile(tga->getData(), tga->getDataSize(), self->mImageID, LLAssetType::AT_IMAGE_TGA); raw->biasedScaleToPowerOfTwo(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT); @@ -209,7 +209,7 @@ void LLFloaterAuction::onClickSnapshot(void* data) LLPointer j2c = new LLImageJ2C; j2c->encode(raw, 0.0f); - LLVFile::writeFile(j2c->getData(), j2c->getDataSize(), self->mImageID, LLAssetType::AT_TEXTURE); + LLDiskCache::writeFile(j2c->getData(), j2c->getDataSize(), self->mImageID, LLAssetType::AT_TEXTURE); self->mImage = LLViewerTextureManager::getLocalTexture((LLImageRaw*)raw, FALSE); gGL.getTexUnit(0)->bind(self->mImage); diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index 88ea3d74fb..303b4836e4 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -32,7 +32,7 @@ #include "lldatapacker.h" #include "lldir.h" #include "llnotificationsutil.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llapr.h" #include "llstring.h" @@ -997,7 +997,7 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata) LLDataPackerBinaryBuffer dp(buffer, file_size); if (motionp->serialize(dp)) { - LLVFile file(motionp->getID(), LLAssetType::AT_ANIMATION, LLVFile::APPEND); + LLDiskCache file(motionp->getID(), LLAssetType::AT_ANIMATION, LLDiskCache::APPEND); S32 size = dp.getCurrentSize(); file.setMaxSize(size); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index bc35975cc6..057c4d0d5c 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -77,7 +77,7 @@ #include "llspinctrl.h" #include "lltoggleablemenu.h" #include "lltrans.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llcallbacklist.h" #include "llviewerobjectlist.h" #include "llanimationstates.h" diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 4b67a0f605..d2ab15a9b4 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -36,7 +36,7 @@ #include "llglheaders.h" #include "llregionflags.h" #include "llstl.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llxfermanager.h" #include "indra_constants.h" #include "message.h" @@ -2239,7 +2239,7 @@ void LLPanelEstateCovenant::onLoadComplete(const LLUUID& asset_uuid, { if(0 == status) { - LLVFile file(asset_uuid, type, LLVFile::READ); + LLDiskCache file(asset_uuid, type, LLDiskCache::READ); S32 file_length = file.getSize(); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 09178166e9..d658352442 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -44,7 +44,7 @@ #include "llnotificationsutil.h" #include "llstring.h" #include "llsys.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "mean_collision_data.h" #include "message.h" #include "v3math.h" @@ -899,7 +899,7 @@ void LLFloaterReporter::takeScreenshot(bool use_prev_screenshot) mResourceDatap->mAssetInfo.setDescription("screenshot_descr"); // store in cache - LLVFile::writeFile(upload_data->getData(), + LLDiskCache::writeFile(upload_data->getData(), upload_data->getDataSize(), mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType); diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index bd403f68d7..96da13915c 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -40,7 +40,7 @@ #include "lltextbox.h" #include "llui.h" #include "lluictrlfactory.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "message.h" #include "llstartup.h" // login_alert_done #include "llcorehttputil.h" diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 119e0d21b2..82feb891bc 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -42,7 +42,7 @@ #include "llnotificationsutil.h" #include "llstl.h" #include "llstring.h" // todo: remove -#include "llvfile.h" +#include "lldiskcache.h" #include "message.h" // newview @@ -1055,7 +1055,7 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid, if (0 == status) { - LLVFile file(asset_uuid, type, LLVFile::READ); + LLDiskCache file(asset_uuid, type, LLDiskCache::READ); S32 size = file.getSize(); std::vector buffer(size+1); diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index 247ebf7719..a139d138f8 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -33,7 +33,7 @@ #include "llappviewer.h" #include "llagent.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llviewerstats.h" // Globals @@ -105,7 +105,7 @@ void LLLandmarkList::processGetAssetReply( { if( status == 0 ) { - LLVFile file(uuid, type); + LLDiskCache file(uuid, type); S32 file_length = file.getSize(); std::vector buffer(file_length + 1); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 55c64508d2..6e58126847 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -49,7 +49,7 @@ #include "llsdutil_math.h" #include "llsdserialize.h" #include "llthread.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llviewercontrol.h" #include "llviewerinventory.h" #include "llviewermenufile.h" @@ -1335,7 +1335,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) { //check cache for mesh skin info - LLVFile file(mesh_id, LLAssetType::AT_MESH); + LLDiskCache file(mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) { U8* buffer = new(std::nothrow) U8[size]; @@ -1431,7 +1431,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) { //check cache for mesh skin info - LLVFile file(mesh_id, LLAssetType::AT_MESH); + LLDiskCache file(mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) { U8* buffer = new(std::nothrow) U8[size]; @@ -1528,7 +1528,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) { //check cache for mesh physics shape info - LLVFile file(mesh_id, LLAssetType::AT_MESH); + LLDiskCache file(mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) { LLMeshRepository::sCacheBytesRead += size; @@ -1633,7 +1633,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, bool c { //look for mesh in asset in cache - LLVFile file(mesh_params.getSculptID(), LLAssetType::AT_MESH); + LLDiskCache file(mesh_params.getSculptID(), LLAssetType::AT_MESH); S32 size = file.getSize(); @@ -1712,7 +1712,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, { //check cache for mesh asset - LLVFile file(mesh_id, LLAssetType::AT_MESH); + LLDiskCache file(mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) { U8* buffer = new(std::nothrow) U8[size]; @@ -3200,7 +3200,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b // only allocate as much space in the cache as is needed for the local cache data_size = llmin(data_size, bytes); - LLVFile file(mesh_id, LLAssetType::AT_MESH, LLVFile::WRITE); + LLDiskCache file(mesh_id, LLAssetType::AT_MESH, LLDiskCache::WRITE); if (file.getMaxSize() >= bytes || file.setMaxSize(bytes)) { LLMeshRepository::sCacheBytesWritten += data_size; @@ -3272,7 +3272,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body if (result == MESH_OK) { // good fetch from sim, write to cache - LLVFile file(mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLVFile::WRITE); + LLDiskCache file(mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLDiskCache::WRITE); S32 offset = mOffset; S32 size = mRequestedBytes; @@ -3336,7 +3336,7 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* && gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size)) { // good fetch from sim, write to cache - LLVFile file(mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); + LLDiskCache file(mMeshID, LLAssetType::AT_MESH, LLDiskCache::WRITE); S32 offset = mOffset; S32 size = mRequestedBytes; @@ -3384,7 +3384,7 @@ void LLMeshDecompositionHandler::processData(LLCore::BufferArray * /* body */, S && gMeshRepo.mThread->decompositionReceived(mMeshID, data, data_size)) { // good fetch from sim, write to cache - LLVFile file(mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); + LLDiskCache file(mMeshID, LLAssetType::AT_MESH, LLDiskCache::WRITE); S32 offset = mOffset; S32 size = mRequestedBytes; @@ -3431,7 +3431,7 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * /* body */, S3 && gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size)) { // good fetch from sim, write to cache for caching - LLVFile file(mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); + LLDiskCache file(mMeshID, LLAssetType::AT_MESH, LLDiskCache::WRITE); S32 offset = mOffset; S32 size = mRequestedBytes; diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 852ba846ff..30604df944 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -32,7 +32,7 @@ // llcommon #include "llcommonutils.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llaccordionctrltab.h" #include "llappearancemgr.h" diff --git a/indra/newview/llpostcard.cpp b/indra/newview/llpostcard.cpp index 5201988d7c..1fd57ef555 100644 --- a/indra/newview/llpostcard.cpp +++ b/indra/newview/llpostcard.cpp @@ -28,7 +28,7 @@ #include "llpostcard.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llviewerregion.h" #include "message.h" diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index aaae6daf2c..c7f8f790f4 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -47,7 +47,7 @@ #include "llradiogroup.h" #include "llresmgr.h" #include "lltrans.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llviewerstats.h" @@ -852,7 +852,7 @@ void LLPreviewGesture::onLoadComplete(const LLUUID& asset_uuid, { if (0 == status) { - LLVFile file(asset_uuid, type, LLVFile::READ); + LLDiskCache file(asset_uuid, type, LLDiskCache::READ); S32 size = file.getSize(); std::vector buffer(size+1); @@ -1137,7 +1137,7 @@ void LLPreviewGesture::saveIfNeeded() tid.generate(); assetId = tid.makeAssetID(gAgent.getSecureSessionID()); - LLVFile file(assetId, LLAssetType::AT_GESTURE, LLVFile::APPEND); + LLDiskCache file(assetId, LLAssetType::AT_GESTURE, LLDiskCache::APPEND); S32 size = dp.getCurrentSize(); file.setMaxSize(size); diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 62ddfd5b3e..0b21ff5047 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -46,7 +46,7 @@ #include "llselectmgr.h" #include "lltrans.h" #include "llviewertexteditor.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llviewerinventory.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" @@ -337,7 +337,7 @@ void LLPreviewNotecard::onLoadComplete(const LLUUID& asset_uuid, { if(0 == status) { - LLVFile file(asset_uuid, type, LLVFile::READ); + LLDiskCache file(asset_uuid, type, LLDiskCache::READ); S32 file_length = file.getSize(); @@ -452,7 +452,7 @@ void LLPreviewNotecard::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, // script actually changed the asset. if (nc->hasEmbeddedInventory()) { - LLVFile::removeFile(newAssetId, LLAssetType::AT_NOTECARD); + LLDiskCache::removeFile(newAssetId, LLAssetType::AT_NOTECARD); } if (newItemId.isNull()) { @@ -477,7 +477,7 @@ void LLPreviewNotecard::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUI { if (nc->hasEmbeddedInventory()) { - LLVFile::removeFile(newAssetId, LLAssetType::AT_NOTECARD); + LLDiskCache::removeFile(newAssetId, LLAssetType::AT_NOTECARD); } nc->setAssetId(newAssetId); nc->refreshFromInventory(); @@ -556,7 +556,7 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem, bool sync) tid.generate(); asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - LLVFile file(asset_id, LLAssetType::AT_NOTECARD, LLVFile::APPEND); + LLDiskCache file(asset_id, LLAssetType::AT_NOTECARD, LLDiskCache::APPEND); LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID, diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 2eedce9bc1..c2b687cf3b 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -51,7 +51,7 @@ #include "llsdserialize.h" #include "llslider.h" #include "lltooldraganddrop.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llagent.h" #include "llmenugl.h" @@ -1715,7 +1715,7 @@ void LLPreviewLSL::onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType t { if(0 == status) { - LLVFile file(asset_uuid, type); + LLDiskCache file(asset_uuid, type); S32 file_length = file.getSize(); std::vector buffer(file_length+1); @@ -2020,7 +2020,7 @@ void LLLiveLSLEditor::onLoadComplete(const LLUUID& asset_id, void LLLiveLSLEditor::loadScriptText(const LLUUID &uuid, LLAssetType::EType type) { - LLVFile file(uuid, type); + LLDiskCache file(uuid, type); S32 file_length = file.getSize(); std::vector buffer(file_length + 1); file.read((U8*)&buffer[0], file_length); diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 0084180cf8..62dc9f24bd 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -57,7 +57,7 @@ #include "llinventorymodel.h" #include "llassetstorage.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "lldrawpoolwater.h" #include @@ -303,7 +303,7 @@ void LLSettingsVOBase::onAssetDownloadComplete(const LLUUID &asset_id, S32 statu LLSettingsBase::ptr_t settings; if (!status) { - LLVFile file(asset_id, LLAssetType::AT_SETTINGS, LLVFile::READ); + LLDiskCache file(asset_id, LLAssetType::AT_SETTINGS, LLDiskCache::READ); S32 size = file.getSize(); std::string buffer(size + 1, '\0'); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 4b8ceba80f..50523e981a 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -50,7 +50,7 @@ #include "llviewercontrol.h" #include "llviewermenufile.h" // upload_new_resource() #include "llviewerstats.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llwindow.h" #include "llworld.h" #include @@ -1005,7 +1005,7 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) if (formatted->encode(scaled, 0.0f)) { - LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), new_asset_id, LLAssetType::AT_TEXTURE); + LLDiskCache::writeFile(formatted->getData(), formatted->getDataSize(), new_asset_id, LLAssetType::AT_TEXTURE); std::string pos_string; LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL); std::string who_took_it; diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index b4e1e2633b..e9c8909fe4 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -28,7 +28,7 @@ #include "llviewerassetstorage.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "message.h" #include "llagent.h" @@ -151,13 +151,13 @@ void LLViewerAssetStorage::storeAssetData( if (mUpstreamHost.isOk()) { - if (LLVFile::getExists(asset_id, asset_type)) + if (LLDiskCache::getExists(asset_id, asset_type)) { // Pack data into this packet if we can fit it. U8 buffer[MTUBYTES]; buffer[0] = 0; - LLVFile vfile(asset_id, asset_type, LLVFile::READ); + LLDiskCache vfile(asset_id, asset_type, LLDiskCache::READ); S32 asset_size = vfile.getSize(); LLAssetRequest *req = new LLAssetRequest(asset_id, asset_type); @@ -179,7 +179,7 @@ void LLViewerAssetStorage::storeAssetData( else { // LLAssetStorage metric: Successful Request - S32 size = LLVFile::getFileSize(asset_id, asset_type); + S32 size = LLDiskCache::getFileSize(asset_id, asset_type); const char *message = "Added to upload queue"; reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, size, MR_OKAY, __FILE__, __LINE__, message ); @@ -290,7 +290,7 @@ void LLViewerAssetStorage::storeAssetData( legacy->mUpCallback = callback; legacy->mUserData = user_data; - LLVFile file(asset_id, asset_type, LLVFile::WRITE); + LLDiskCache file(asset_id, asset_type, LLDiskCache::WRITE); file.setMaxSize(size); @@ -526,7 +526,7 @@ void LLViewerAssetStorage::assetRequestCoro( // case. LLUUID temp_id; temp_id.generate(); - LLVFile vf(temp_id, atype, LLVFile::WRITE); + LLDiskCache vf(temp_id, atype, LLDiskCache::WRITE); vf.setMaxSize(size); req->mBytesFetched = size; if (!vf.write(raw.data(),size)) diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index 5d3f01fbb5..e65bdc1aea 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -30,7 +30,7 @@ #include "llassetstorage.h" #include "llcorehttputil.h" -class LLVFile; +class LLDiskCache; class LLViewerAssetRequest; diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index d14b6b0568..d62962514c 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -45,7 +45,7 @@ #include "llviewerassetupload.h" #include "llappviewer.h" #include "llviewerstats.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llgesturemgr.h" #include "llpreviewnotecard.h" #include "llpreviewgesture.h" @@ -472,7 +472,7 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile() infile.open(filename, LL_APR_RB, NULL, &file_size); if (infile.getFileHandle()) { - LLVFile file(getAssetId(), assetType, LLVFile::WRITE); + LLDiskCache file(getAssetId(), assetType, LLDiskCache::WRITE); file.setMaxSize(file_size); @@ -565,7 +565,7 @@ LLSD LLBufferedAssetUploadInfo::prepareUpload() if (getAssetId().isNull()) generateNewAssetId(); - LLVFile file(getAssetId(), getAssetType(), LLVFile::APPEND); + LLDiskCache file(getAssetId(), getAssetType(), LLDiskCache::APPEND); S32 size = mContents.length() + 1; file.setMaxSize(size); @@ -597,7 +597,7 @@ LLUUID LLBufferedAssetUploadInfo::finishUpload(LLSD &result) if (mStoredToCache) { LLAssetType::EType assetType(getAssetType()); - LLVFile::renameFile(getAssetId(), assetType, newAssetId, assetType); + LLDiskCache::renameFile(getAssetId(), assetType, newAssetId, assetType); } if (mTaskUpload) diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index cbf490d68d..6d4e12528d 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -53,7 +53,7 @@ #include "llviewercontrol.h" // gSavedSettings #include "llviewertexturelist.h" #include "lluictrlfactory.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llviewerinventory.h" #include "llviewermenu.h" // gMenuHolder #include "llviewerparcelmgr.h" diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 2d41560441..10ee92c130 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -44,7 +44,7 @@ #include "llteleportflags.h" #include "lltoastnotifypanel.h" #include "lltransactionflags.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llxfermanager.h" #include "mean_collision_data.h" @@ -6816,7 +6816,7 @@ void onCovenantLoadComplete(const LLUUID& asset_uuid, std::string covenant_text; if(0 == status) { - LLVFile file(asset_uuid, type, LLVFile::READ); + LLDiskCache file(asset_uuid, type, LLDiskCache::READ); S32 file_length = file.getSize(); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 470704d84e..874982ed60 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -33,7 +33,7 @@ #include "llfloaterreg.h" #include "llmemory.h" #include "lltimer.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llappviewer.h" diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp index b1cbdc4443..5c36635923 100644 --- a/indra/newview/llviewertexlayer.cpp +++ b/indra/newview/llviewertexlayer.cpp @@ -31,7 +31,7 @@ #include "llagent.h" #include "llimagej2c.h" #include "llnotificationsutil.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llviewerregion.h" #include "llglslshader.h" #include "llvoavatarself.h" diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 8782f282bf..f12ab59e2b 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -39,7 +39,7 @@ #include "llimagej2c.h" #include "llimagetga.h" #include "llstl.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "message.h" #include "lltimer.h" diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 69568cc825..57a2421065 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -54,7 +54,7 @@ class LLTexturePipelineTester ; typedef void (*loaded_callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); -class LLVFile; +class LLDiskCache; class LLMessageSystem; class LLViewerMediaImpl ; class LLVOVolume ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 312a8726ca..e0727d51ba 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -41,7 +41,7 @@ #include "llsdserialize.h" #include "llsys.h" -#include "llvfile.h" +#include "lldiskcache.h" #include "llxmltree.h" #include "message.h" -- cgit v1.3 From d9448c6f52218146113d1d5c5ca4c4d5f01dc5cf Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 17 Sep 2020 09:45:06 -0700 Subject: The folder where the disk cache lives was originally renamed from llvfs to llcache but @henri's suggestion that that doesn't reflect the other files in the same place and it should be llfilesystem is a good one so I changed it over --- indra/CMakeLists.txt | 2 +- indra/cmake/CMakeLists.txt | 2 +- indra/cmake/LLCache.cmake | 7 - indra/cmake/LLFileSystem.cmake | 7 + indra/llappearance/CMakeLists.txt | 20 +- indra/llaudio/CMakeLists.txt | 6 +- indra/llcache/CMakeLists.txt | 98 -- indra/llcache/lldir.cpp | 1134 ----------------------- indra/llcache/lldir.h | 280 ------ indra/llcache/lldir_linux.cpp | 269 ------ indra/llcache/lldir_linux.h | 64 -- indra/llcache/lldir_mac.cpp | 205 ---- indra/llcache/lldir_mac.h | 56 -- indra/llcache/lldir_solaris.cpp | 266 ------ indra/llcache/lldir_solaris.h | 61 -- indra/llcache/lldir_utils_objc.h | 43 - indra/llcache/lldir_utils_objc.mm | 108 --- indra/llcache/lldir_win32.cpp | 452 --------- indra/llcache/lldir_win32.h | 59 -- indra/llcache/lldirguard.h | 72 -- indra/llcache/lldiriterator.cpp | 243 ----- indra/llcache/lldiriterator.h | 87 -- indra/llcache/lldiskcache.cpp | 387 -------- indra/llcache/lldiskcache.h | 82 -- indra/llcache/lllfsthread.cpp | 245 ----- indra/llcache/lllfsthread.h | 147 --- indra/llcache/tests/lldir_test.cpp | 767 --------------- indra/llcache/tests/lldiriterator_test.cpp | 65 -- indra/llcharacter/CMakeLists.txt | 6 +- indra/llcrashlogger/CMakeLists.txt | 4 +- indra/llfilesystem/CMakeLists.txt | 98 ++ indra/llfilesystem/lldir.cpp | 1134 +++++++++++++++++++++++ indra/llfilesystem/lldir.h | 280 ++++++ indra/llfilesystem/lldir_linux.cpp | 269 ++++++ indra/llfilesystem/lldir_linux.h | 64 ++ indra/llfilesystem/lldir_mac.cpp | 205 ++++ indra/llfilesystem/lldir_mac.h | 56 ++ indra/llfilesystem/lldir_solaris.cpp | 266 ++++++ indra/llfilesystem/lldir_solaris.h | 61 ++ indra/llfilesystem/lldir_utils_objc.h | 43 + indra/llfilesystem/lldir_utils_objc.mm | 108 +++ indra/llfilesystem/lldir_win32.cpp | 452 +++++++++ indra/llfilesystem/lldir_win32.h | 59 ++ indra/llfilesystem/lldirguard.h | 72 ++ indra/llfilesystem/lldiriterator.cpp | 243 +++++ indra/llfilesystem/lldiriterator.h | 87 ++ indra/llfilesystem/lldiskcache.cpp | 387 ++++++++ indra/llfilesystem/lldiskcache.h | 82 ++ indra/llfilesystem/lllfsthread.cpp | 245 +++++ indra/llfilesystem/lllfsthread.h | 147 +++ indra/llfilesystem/tests/lldir_test.cpp | 767 +++++++++++++++ indra/llfilesystem/tests/lldiriterator_test.cpp | 65 ++ indra/llimage/CMakeLists.txt | 6 +- indra/llinventory/CMakeLists.txt | 4 +- indra/llmessage/CMakeLists.txt | 12 +- indra/llrender/CMakeLists.txt | 10 +- indra/llui/CMakeLists.txt | 6 +- indra/llwindow/CMakeLists.txt | 8 +- indra/llxml/CMakeLists.txt | 6 +- indra/mac_crash_logger/CMakeLists.txt | 6 +- indra/newview/CMakeLists.txt | 10 +- indra/test/CMakeLists.txt | 7 +- indra/win_crash_logger/CMakeLists.txt | 6 +- 63 files changed, 5250 insertions(+), 5265 deletions(-) delete mode 100644 indra/cmake/LLCache.cmake create mode 100644 indra/cmake/LLFileSystem.cmake delete mode 100644 indra/llcache/CMakeLists.txt delete mode 100644 indra/llcache/lldir.cpp delete mode 100644 indra/llcache/lldir.h delete mode 100644 indra/llcache/lldir_linux.cpp delete mode 100644 indra/llcache/lldir_linux.h delete mode 100644 indra/llcache/lldir_mac.cpp delete mode 100644 indra/llcache/lldir_mac.h delete mode 100644 indra/llcache/lldir_solaris.cpp delete mode 100644 indra/llcache/lldir_solaris.h delete mode 100644 indra/llcache/lldir_utils_objc.h delete mode 100644 indra/llcache/lldir_utils_objc.mm delete mode 100644 indra/llcache/lldir_win32.cpp delete mode 100644 indra/llcache/lldir_win32.h delete mode 100644 indra/llcache/lldirguard.h delete mode 100644 indra/llcache/lldiriterator.cpp delete mode 100644 indra/llcache/lldiriterator.h delete mode 100644 indra/llcache/lldiskcache.cpp delete mode 100644 indra/llcache/lldiskcache.h delete mode 100644 indra/llcache/lllfsthread.cpp delete mode 100644 indra/llcache/lllfsthread.h delete mode 100644 indra/llcache/tests/lldir_test.cpp delete mode 100644 indra/llcache/tests/lldiriterator_test.cpp create mode 100644 indra/llfilesystem/CMakeLists.txt create mode 100644 indra/llfilesystem/lldir.cpp create mode 100644 indra/llfilesystem/lldir.h create mode 100644 indra/llfilesystem/lldir_linux.cpp create mode 100644 indra/llfilesystem/lldir_linux.h create mode 100644 indra/llfilesystem/lldir_mac.cpp create mode 100644 indra/llfilesystem/lldir_mac.h create mode 100644 indra/llfilesystem/lldir_solaris.cpp create mode 100644 indra/llfilesystem/lldir_solaris.h create mode 100644 indra/llfilesystem/lldir_utils_objc.h create mode 100644 indra/llfilesystem/lldir_utils_objc.mm create mode 100644 indra/llfilesystem/lldir_win32.cpp create mode 100644 indra/llfilesystem/lldir_win32.h create mode 100644 indra/llfilesystem/lldirguard.h create mode 100644 indra/llfilesystem/lldiriterator.cpp create mode 100644 indra/llfilesystem/lldiriterator.h create mode 100644 indra/llfilesystem/lldiskcache.cpp create mode 100644 indra/llfilesystem/lldiskcache.h create mode 100644 indra/llfilesystem/lllfsthread.cpp create mode 100644 indra/llfilesystem/lllfsthread.h create mode 100644 indra/llfilesystem/tests/lldir_test.cpp create mode 100644 indra/llfilesystem/tests/lldiriterator_test.cpp (limited to 'indra/llui') diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 04279cc887..4b39bfe332 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -40,7 +40,7 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llmath) add_subdirectory(${LIBS_OPEN_PREFIX}llmessage) add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive) add_subdirectory(${LIBS_OPEN_PREFIX}llrender) -add_subdirectory(${LIBS_OPEN_PREFIX}llcache) +add_subdirectory(${LIBS_OPEN_PREFIX}llfilesystem) add_subdirectory(${LIBS_OPEN_PREFIX}llwindow) add_subdirectory(${LIBS_OPEN_PREFIX}llxml) diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index d464c8ad74..352dfc0641 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -69,7 +69,7 @@ set(cmake_SOURCE_FILES LLSharedLibs.cmake LLTestCommand.cmake LLUI.cmake - LLCache.cmake + LLFileSystem.cmake LLWindow.cmake LLXML.cmake Linking.cmake diff --git a/indra/cmake/LLCache.cmake b/indra/cmake/LLCache.cmake deleted file mode 100644 index 6a82774133..0000000000 --- a/indra/cmake/LLCache.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# -*- cmake -*- - -set(LLCACHE_INCLUDE_DIRS - ${LIBS_OPEN_DIR}/llcache - ) - -set(LLCACHE_LIBRARIES llcache) diff --git a/indra/cmake/LLFileSystem.cmake b/indra/cmake/LLFileSystem.cmake new file mode 100644 index 0000000000..2e6c42c30c --- /dev/null +++ b/indra/cmake/LLFileSystem.cmake @@ -0,0 +1,7 @@ +# -*- cmake -*- + +set(LLFILESYSTEM_INCLUDE_DIRS + ${LIBS_OPEN_DIR}/llfilesystem + ) + +set(LLFILESYSTEM_LIBRARIES llfilesystem) diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index ff784387dc..268849ad74 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -11,7 +11,7 @@ include(LLMath) include(LLMessage) include(LLCoreHttp) include(LLRender) -include(LLCache) +include(LLFileSystem) include(LLWindow) include(LLXML) include(Linking) @@ -23,7 +23,7 @@ include_directories( ${LLINVENTORY_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ) @@ -83,7 +83,7 @@ target_link_libraries(llappearance ${LLINVENTORY_LIBRARIES} ${LLIMAGE_LIBRARIES} ${LLRENDER_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLMATH_LIBRARIES} ${LLXML_LIBRARIES} ${LLMATH_LIBRARIES} @@ -100,7 +100,7 @@ if (BUILD_HEADLESS) ${LLINVENTORY_LIBRARIES} ${LLIMAGE_LIBRARIES} ${LLRENDERHEADLESS_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLMATH_LIBRARIES} ${LLXML_LIBRARIES} ${LLMATH_LIBRARIES} @@ -109,15 +109,3 @@ if (BUILD_HEADLESS) ${LLCOMMON_LIBRARIES} ) endif (BUILD_HEADLESS) - -#add unit tests -#if (LL_TESTS) -# INCLUDE(LLAddBuildTest) -# SET(llappearance_TEST_SOURCE_FILES -# # no real unit tests yet! -# ) -# LL_ADD_PROJECT_UNIT_TESTS(llappearance "${llappearance_TEST_SOURCE_FILES}") - - #set(TEST_DEBUG on) -# set(test_libs llappearance ${LLCOMMON_LIBRARIES}) -#endif (LL_TESTS) diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt index 2498561029..9dcd4d697e 100644 --- a/indra/llaudio/CMakeLists.txt +++ b/indra/llaudio/CMakeLists.txt @@ -9,14 +9,14 @@ include(OPENAL) include(LLCommon) include(LLMath) include(LLMessage) -include(LLCache) +include(LLFileSystem) include_directories( ${LLAUDIO_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${OGG_INCLUDE_DIRS} ${VORBISENC_INCLUDE_DIRS} ${VORBISFILE_INCLUDE_DIRS} @@ -82,7 +82,7 @@ target_link_libraries( ${LLCOMMON_LIBRARIES} ${LLMATH_LIBRARIES} ${LLMESSAGE_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${VORBISENC_LIBRARIES} ${VORBISFILE_LIBRARIES} ${VORBIS_LIBRARIES} diff --git a/indra/llcache/CMakeLists.txt b/indra/llcache/CMakeLists.txt deleted file mode 100644 index f1e4e7e0a3..0000000000 --- a/indra/llcache/CMakeLists.txt +++ /dev/null @@ -1,98 +0,0 @@ -# -*- cmake -*- - -project(llcache) - -include(00-Common) -include(LLCommon) -include(UnixInstall) - -include_directories( - ${LLCOMMON_INCLUDE_DIRS} - ${LLCOMMON_SYSTEM_INCLUDE_DIRS} - ) - -set(llcache_SOURCE_FILES - lldir.cpp - lldiriterator.cpp - lllfsthread.cpp - lldiskcache.cpp - ) - -set(llcache_HEADER_FILES - CMakeLists.txt - - lldir.h - lldirguard.h - lldiriterator.h - lllfsthread.h - lldiskcache.h - ) - -if (DARWIN) - LIST(APPEND llcache_SOURCE_FILES lldir_utils_objc.mm) - LIST(APPEND llcache_SOURCE_FILES lldir_utils_objc.h) - LIST(APPEND llcache_SOURCE_FILES lldir_mac.cpp) - LIST(APPEND llcache_HEADER_FILES lldir_mac.h) -endif (DARWIN) - -if (LINUX) - LIST(APPEND llcache_SOURCE_FILES lldir_linux.cpp) - LIST(APPEND llcache_HEADER_FILES lldir_linux.h) - - if (INSTALL) - set_source_files_properties(lldir_linux.cpp - PROPERTIES COMPILE_FLAGS - "-DAPP_RO_DATA_DIR=\\\"${APP_SHARE_DIR}\\\"" - ) - endif (INSTALL) -endif (LINUX) - -if (WINDOWS) - LIST(APPEND llcache_SOURCE_FILES lldir_win32.cpp) - LIST(APPEND llcache_HEADER_FILES lldir_win32.h) -endif (WINDOWS) - -set_source_files_properties(${llcache_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - -list(APPEND llcache_SOURCE_FILES ${llcache_HEADER_FILES}) - -add_library (llcache ${llcache_SOURCE_FILES}) - -set(cache_BOOST_LIBRARIES - ${BOOST_FILESYSTEM_LIBRARY} - ${BOOST_SYSTEM_LIBRARY} - ) - -target_link_libraries(llcache - ${LLCOMMON_LIBRARIES} - ${cache_BOOST_LIBRARIES} - ) - -if (DARWIN) - include(CMakeFindFrameworks) - find_library(COCOA_LIBRARY Cocoa) - target_link_libraries(llcache ${COCOA_LIBRARY}) -endif (DARWIN) - - -# Add tests -if (LL_TESTS) - include(LLAddBuildTest) - # UNIT TESTS - SET(llcache_TEST_SOURCE_FILES - lldiriterator.cpp - ) - - set_source_files_properties(lldiriterator.cpp - PROPERTIES - LL_TEST_ADDITIONAL_LIBRARIES "${cache_BOOST_LIBRARIES}" - ) - LL_ADD_PROJECT_UNIT_TESTS(llcache "${llcache_TEST_SOURCE_FILES}") - - # INTEGRATION TESTS - set(test_libs llmath llcommon llcache ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) - - # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests. - LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}") -endif (LL_TESTS) diff --git a/indra/llcache/lldir.cpp b/indra/llcache/lldir.cpp deleted file mode 100644 index 10fbc06c61..0000000000 --- a/indra/llcache/lldir.cpp +++ /dev/null @@ -1,1134 +0,0 @@ -/** - * @file lldir.cpp - * @brief implementation of directory utilities base class - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#if !LL_WINDOWS -#include -#include -#include -#else -#include -#endif - -#include "lldir.h" - -#include "llerror.h" -#include "lltimer.h" // ms_sleep() -#include "lluuid.h" - -#include "lldiriterator.h" -#include "stringize.h" -#include "llstring.h" -#include -#include -#include -#include -#include -#include -#include -#include - -using boost::assign::list_of; -using boost::assign::map_list_of; - -#if LL_WINDOWS -#include "lldir_win32.h" -LLDir_Win32 gDirUtil; -#elif LL_DARWIN -#include "lldir_mac.h" -LLDir_Mac gDirUtil; -#elif LL_SOLARIS -#include "lldir_solaris.h" -LLDir_Solaris gDirUtil; -#else -#include "lldir_linux.h" -LLDir_Linux gDirUtil; -#endif - -LLDir *gDirUtilp = (LLDir *)&gDirUtil; - -/// Values for findSkinnedFilenames(subdir) parameter -const char - *LLDir::XUI = "xui", - *LLDir::TEXTURES = "textures", - *LLDir::SKINBASE = ""; - -static const char* const empty = ""; -std::string LLDir::sDumpDir = ""; - -LLDir::LLDir() -: mAppName(""), - mExecutablePathAndName(""), - mExecutableFilename(""), - mExecutableDir(""), - mAppRODataDir(""), - mOSUserDir(""), - mOSUserAppDir(""), - mLindenUserDir(""), - mOSCacheDir(""), - mCAFile(""), - mTempDir(""), - mDirDelimiter("/"), // fallback to forward slash if not overridden - mLanguage("en"), - mUserName("undefined") -{ -} - -LLDir::~LLDir() -{ -} - -std::vector LLDir::getFilesInDir(const std::string &dirname) -{ - //Returns a vector of fullpath filenames. - -#ifdef LL_WINDOWS // or BOOST_WINDOWS_API - boost::filesystem::path p(utf8str_to_utf16str(dirname)); -#else - boost::filesystem::path p(dirname); -#endif - - std::vector v; - - if (exists(p)) - { - if (is_directory(p)) - { - boost::filesystem::directory_iterator end_iter; - for (boost::filesystem::directory_iterator dir_itr(p); - dir_itr != end_iter; - ++dir_itr) - { - if (boost::filesystem::is_regular_file(dir_itr->status())) - { - v.push_back(dir_itr->path().filename().string()); - } - } - } - } - return v; -} - -S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) -{ - S32 count = 0; - std::string filename; - std::string fullpath; - S32 result; - - // File masks starting with "/" will match nothing, so we consider them invalid. - if (LLStringUtil::startsWith(mask, getDirDelimiter())) - { - LL_WARNS() << "Invalid file mask: " << mask << LL_ENDL; - llassert(!"Invalid file mask"); - } - - LLDirIterator iter(dirname, mask); - while (iter.next(filename)) - { - fullpath = add(dirname, filename); - - if(LLFile::isdir(fullpath)) - { - // skipping directory traversal filenames - count++; - continue; - } - - S32 retry_count = 0; - while (retry_count < 5) - { - if (0 != LLFile::remove(fullpath)) - { - retry_count++; - result = errno; - LL_WARNS() << "Problem removing " << fullpath << " - errorcode: " - << result << " attempt " << retry_count << LL_ENDL; - - if(retry_count >= 5) - { - LL_WARNS() << "Failed to remove " << fullpath << LL_ENDL ; - return count ; - } - - ms_sleep(100); - } - else - { - if (retry_count) - { - LL_WARNS() << "Successfully removed " << fullpath << LL_ENDL; - } - break; - } - } - count++; - } - return count; -} - -U32 LLDir::deleteDirAndContents(const std::string& dir_name) -{ - //Removes the directory and its contents. Returns number of files deleted. - - U32 num_deleted = 0; - - try - { -#ifdef LL_WINDOWS // or BOOST_WINDOWS_API - boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name)); -#else - boost::filesystem::path dir_path(dir_name); -#endif - - if (boost::filesystem::exists (dir_path)) - { - if (!boost::filesystem::is_empty (dir_path)) - { // Directory has content - num_deleted = boost::filesystem::remove_all (dir_path); - } - else - { // Directory is empty - boost::filesystem::remove (dir_path); - } - } - } - catch (boost::filesystem::filesystem_error &er) - { - LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL; - } - return num_deleted; -} - -const std::string LLDir::findFile(const std::string &filename, - const std::string& searchPath1, - const std::string& searchPath2, - const std::string& searchPath3) const -{ - std::vector search_paths; - search_paths.push_back(searchPath1); - search_paths.push_back(searchPath2); - search_paths.push_back(searchPath3); - return findFile(filename, search_paths); -} - -const std::string LLDir::findFile(const std::string& filename, const std::vector search_paths) const -{ - std::vector::const_iterator search_path_iter; - for (search_path_iter = search_paths.begin(); - search_path_iter != search_paths.end(); - ++search_path_iter) - { - if (!search_path_iter->empty()) - { - std::string filename_and_path = (*search_path_iter); - if (!filename.empty()) - { - filename_and_path += getDirDelimiter() + filename; - } - if (fileExists(filename_and_path)) - { - return filename_and_path; - } - } - } - return ""; -} - - -const std::string &LLDir::getExecutablePathAndName() const -{ - return mExecutablePathAndName; -} - -const std::string &LLDir::getExecutableFilename() const -{ - return mExecutableFilename; -} - -const std::string &LLDir::getExecutableDir() const -{ - return mExecutableDir; -} - -const std::string &LLDir::getWorkingDir() const -{ - return mWorkingDir; -} - -const std::string &LLDir::getAppName() const -{ - return mAppName; -} - -const std::string &LLDir::getAppRODataDir() const -{ - return mAppRODataDir; -} - -const std::string &LLDir::getOSUserDir() const -{ - return mOSUserDir; -} - -const std::string &LLDir::getOSUserAppDir() const -{ - return mOSUserAppDir; -} - -const std::string &LLDir::getLindenUserDir() const -{ - if (mLindenUserDir.empty()) - { - LL_DEBUGS() << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << LL_ENDL; - } - - return mLindenUserDir; -} - -const std::string& LLDir::getChatLogsDir() const -{ - return mChatLogsDir; -} - -void LLDir::setDumpDir( const std::string& path ) -{ - LLDir::sDumpDir = path; - if (LLStringUtil::endsWith(sDumpDir, mDirDelimiter)) - { - sDumpDir.erase(sDumpDir.size() - mDirDelimiter.size()); - } -} - -const std::string &LLDir::getDumpDir() const -{ - if (sDumpDir.empty() ) - { - LLUUID uid; - uid.generate(); - - sDumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "") - + "dump-" + uid.asString(); - - dir_exists_or_crash(sDumpDir); - } - - return LLDir::sDumpDir; -} - -const std::string &LLDir::getPerAccountChatLogsDir() const -{ - return mPerAccountChatLogsDir; -} - -const std::string &LLDir::getTempDir() const -{ - return mTempDir; -} - -const std::string LLDir::getCacheDir(bool get_default) const -{ - if (mCacheDir.empty() || get_default) - { - if (!mDefaultCacheDir.empty()) - { // Set at startup - can't set here due to const API - return mDefaultCacheDir; - } - - std::string res = buildSLOSCacheDir(); - return res; - } - else - { - return mCacheDir; - } -} - -// Return the default cache directory -std::string LLDir::buildSLOSCacheDir() const -{ - std::string res; - if (getOSCacheDir().empty()) - { - if (getOSUserAppDir().empty()) - { - res = "data"; - } - else - { - res = add(getOSUserAppDir(), "cache"); - } - } - else - { - res = add(getOSCacheDir(), "SecondLife"); - } - return res; -} - - - -const std::string &LLDir::getOSCacheDir() const -{ - return mOSCacheDir; -} - - -const std::string &LLDir::getCAFile() const -{ - return mCAFile; -} - -const std::string &LLDir::getDirDelimiter() const -{ - return mDirDelimiter; -} - -const std::string& LLDir::getDefaultSkinDir() const -{ - return mDefaultSkinDir; -} - -const std::string &LLDir::getSkinDir() const -{ - return mSkinDir; -} - -const std::string &LLDir::getUserDefaultSkinDir() const -{ - return mUserDefaultSkinDir; -} - -const std::string &LLDir::getUserSkinDir() const -{ - return mUserSkinDir; -} - -const std::string LLDir::getSkinBaseDir() const -{ - return mSkinBaseDir; -} - -const std::string &LLDir::getLLPluginDir() const -{ - return mLLPluginDir; -} - -const std::string &LLDir::getUserName() const -{ - return mUserName; -} - -static std::string ELLPathToString(ELLPath location) -{ - typedef std::map ELLPathMap; -#define ENT(symbol) (symbol, #symbol) - static const ELLPathMap sMap = map_list_of - ENT(LL_PATH_NONE) - ENT(LL_PATH_USER_SETTINGS) - ENT(LL_PATH_APP_SETTINGS) - ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet - ENT(LL_PATH_CACHE) - ENT(LL_PATH_CHARACTER) - ENT(LL_PATH_HELP) - ENT(LL_PATH_LOGS) - ENT(LL_PATH_TEMP) - ENT(LL_PATH_SKINS) - ENT(LL_PATH_TOP_SKIN) - ENT(LL_PATH_CHAT_LOGS) - ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS) - ENT(LL_PATH_USER_SKIN) - ENT(LL_PATH_LOCAL_ASSETS) - ENT(LL_PATH_EXECUTABLE) - ENT(LL_PATH_DEFAULT_SKIN) - ENT(LL_PATH_FONTS) - ENT(LL_PATH_LAST) - ; -#undef ENT - - ELLPathMap::const_iterator found = sMap.find(location); - if (found != sMap.end()) - return found->second; - return STRINGIZE("Invalid ELLPath value " << location); -} - -std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const -{ - return getExpandedFilename(location, "", filename); -} - -std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir, const std::string& filename) const -{ - return getExpandedFilename(location, "", subdir, filename); -} - -std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir1, const std::string& subdir2, const std::string& in_filename) const -{ - std::string prefix; - switch (location) - { - case LL_PATH_NONE: - // Do nothing - break; - - case LL_PATH_APP_SETTINGS: - prefix = add(getAppRODataDir(), "app_settings"); - break; - - case LL_PATH_CHARACTER: - prefix = add(getAppRODataDir(), "character"); - break; - - case LL_PATH_HELP: - prefix = "help"; - break; - - case LL_PATH_CACHE: - prefix = getCacheDir(); - break; - - case LL_PATH_DUMP: - prefix=getDumpDir(); - break; - - case LL_PATH_USER_SETTINGS: - prefix = add(getOSUserAppDir(), "user_settings"); - break; - - case LL_PATH_PER_SL_ACCOUNT: - prefix = getLindenUserDir(); - if (prefix.empty()) - { - // if we're asking for the per-SL-account directory but we haven't - // logged in yet (or otherwise don't know the account name from - // which to build this string), then intentionally return a blank - // string to the caller and skip the below warning about a blank - // prefix. - LL_DEBUGS("LLDir") << "getLindenUserDir() not yet set: " - << ELLPathToString(location) - << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename - << "' => ''" << LL_ENDL; - return std::string(); - } - break; - - case LL_PATH_CHAT_LOGS: - prefix = getChatLogsDir(); - break; - - case LL_PATH_PER_ACCOUNT_CHAT_LOGS: - prefix = getPerAccountChatLogsDir(); - if (prefix.empty()) - { - // potentially directory was not set yet - // intentionally return a blank string to the caller - LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL; - return std::string(); - } - break; - - case LL_PATH_LOGS: - prefix = add(getOSUserAppDir(), "logs"); - break; - - case LL_PATH_TEMP: - prefix = getTempDir(); - break; - - case LL_PATH_TOP_SKIN: - prefix = getSkinDir(); - break; - - case LL_PATH_DEFAULT_SKIN: - prefix = getDefaultSkinDir(); - break; - - case LL_PATH_USER_SKIN: - prefix = getUserSkinDir(); - break; - - case LL_PATH_SKINS: - prefix = getSkinBaseDir(); - break; - - case LL_PATH_LOCAL_ASSETS: - prefix = add(getAppRODataDir(), "local_assets"); - break; - - case LL_PATH_EXECUTABLE: - prefix = getExecutableDir(); - break; - - case LL_PATH_FONTS: - prefix = add(getAppRODataDir(), "fonts"); - break; - - default: - llassert(0); - } - - if (prefix.empty()) - { - LL_WARNS() << ELLPathToString(location) - << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename - << "': prefix is empty, possible bad filename" << LL_ENDL; - } - - std::string expanded_filename = add(prefix, subdir1, subdir2); - if (expanded_filename.empty() && in_filename.empty()) - { - return ""; - } - // Use explicit concatenation here instead of another add() call. Callers - // passing in_filename as "" expect to obtain a pathname ending with - // mDirSeparator so they can later directly concatenate with a specific - // filename. A caller using add() doesn't care, but there's still code - // loose in the system that uses std::string::operator+(). - expanded_filename += mDirDelimiter; - expanded_filename += in_filename; - - LL_DEBUGS("LLDir") << ELLPathToString(location) - << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename - << "' => '" << expanded_filename << "'" << LL_ENDL; - return expanded_filename; -} - -std::string LLDir::getBaseFileName(const std::string& filepath, bool strip_exten) const -{ - std::size_t offset = filepath.find_last_of(getDirDelimiter()); - offset = (offset == std::string::npos) ? 0 : offset+1; - std::string res = filepath.substr(offset, std::string::npos); - if (strip_exten) - { - offset = res.find_last_of('.'); - if (offset != std::string::npos && - offset != 0) // if basename STARTS with '.', don't strip - { - res = res.substr(0, offset); - } - } - return res; -} - -std::string LLDir::getDirName(const std::string& filepath) const -{ - std::size_t offset = filepath.find_last_of(getDirDelimiter()); - S32 len = (offset == std::string::npos) ? 0 : offset; - std::string dirname = filepath.substr(0, len); - return dirname; -} - -std::string LLDir::getExtension(const std::string& filepath) const -{ - if (filepath.empty()) - return std::string(); - std::string basename = getBaseFileName(filepath, false); - std::size_t offset = basename.find_last_of('.'); - std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1); - LLStringUtil::toLower(exten); - return exten; -} - -std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir, - const std::string &filename, - ESkinConstraint constraint) const -{ - // This implementation is basically just as described in the declaration comments. - std::vector found(findSkinnedFilenames(subdir, filename, constraint)); - if (found.empty()) - { - return ""; - } - return found.front(); -} - -std::string LLDir::findSkinnedFilename(const std::string &subdir, - const std::string &filename, - ESkinConstraint constraint) const -{ - // This implementation is basically just as described in the declaration comments. - std::vector found(findSkinnedFilenames(subdir, filename, constraint)); - if (found.empty()) - { - return ""; - } - return found.back(); -} - -// This method exists because the two code paths for -// findSkinnedFilenames(ALL_SKINS) and findSkinnedFilenames(CURRENT_SKIN) must -// generate the list of candidate pathnames in identical ways. The only -// difference is in the body of the inner loop. -template -void LLDir::walkSearchSkinDirs(const std::string& subdir, - const std::vector& subsubdirs, - const std::string& filename, - const FUNCTION& function) const -{ - BOOST_FOREACH(std::string skindir, mSearchSkinDirs) - { - std::string subdir_path(add(skindir, subdir)); - BOOST_FOREACH(std::string subsubdir, subsubdirs) - { - std::string full_path(add(subdir_path, subsubdir, filename)); - if (fileExists(full_path)) - { - function(subsubdir, full_path); - } - } - } -} - -// ridiculous little helper function that should go away when we can use lambda -inline void push_back(std::vector& vector, const std::string& value) -{ - vector.push_back(value); -} - -typedef std::map StringMap; -// ridiculous little helper function that should go away when we can use lambda -inline void store_in_map(StringMap& map, const std::string& key, const std::string& value) -{ - map[key] = value; -} - -std::vector LLDir::findSkinnedFilenames(const std::string& subdir, - const std::string& filename, - ESkinConstraint constraint) const -{ - // Recognize subdirs that have no localization. - static const std::set sUnlocalized = list_of - ("") // top-level directory not localized - ("textures") // textures not localized - ; - - LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename - << "', constraint " - << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS") - << LL_ENDL; - - // Build results vector. - std::vector results; - // Disallow filenames that may escape subdir - if (filename.find("..") != std::string::npos) - { - LL_WARNS("LLDir") << "Ignoring potentially relative filename '" << filename << "'" << LL_ENDL; - return results; - } - - // Cache the default language directory for each subdir we've encountered. - // A cache entry whose value is the empty string means "not localized, - // don't bother checking again." - static StringMap sLocalized; - - // Check whether we've already discovered if this subdir is localized. - StringMap::const_iterator found = sLocalized.find(subdir); - if (found == sLocalized.end()) - { - // We have not yet determined that. Is it one of the subdirs "known" - // to be unlocalized? - if (sUnlocalized.find(subdir) != sUnlocalized.end()) - { - // This subdir is known to be unlocalized. Remember that. - found = sLocalized.insert(StringMap::value_type(subdir, "")).first; - } - else - { - // We do not recognize this subdir. Investigate. - std::string subdir_path(add(getDefaultSkinDir(), subdir)); - if (fileExists(add(subdir_path, "en"))) - { - // defaultSkinDir/subdir contains subdir "en". That's our - // default language; this subdir is localized. - found = sLocalized.insert(StringMap::value_type(subdir, "en")).first; - } - else if (fileExists(add(subdir_path, "en-us"))) - { - // defaultSkinDir/subdir contains subdir "en-us" but not "en". - // Set as default language; this subdir is localized. - found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first; - } - else - { - // defaultSkinDir/subdir contains neither "en" nor "en-us". - // Assume it's not localized. Remember that assumption. - found = sLocalized.insert(StringMap::value_type(subdir, "")).first; - } - } - } - // Every code path above should have resulted in 'found' becoming a valid - // iterator to an entry in sLocalized. - llassert(found != sLocalized.end()); - - // Now -- is this subdir localized, or not? The answer determines what - // subdirectories we check (under subdir) for the requested filename. - std::vector subsubdirs; - if (found->second.empty()) - { - // subdir is not localized. filename should be located directly within it. - subsubdirs.push_back(""); - } - else - { - // subdir is localized, and found->second is the default language - // directory within it. Check both the default language and the - // current language -- if it differs from the default, of course. - subsubdirs.push_back(found->second); - if (mLanguage != found->second) - { - subsubdirs.push_back(mLanguage); - } - } - - // The process we use depends on 'constraint'. - if (constraint != CURRENT_SKIN) // meaning ALL_SKINS - { - // ALL_SKINS is simpler: just return every pathname generated by - // walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its - // FUNCTION the subsubdir as well as the full pathname. We just want - // the full pathname. - walkSearchSkinDirs(subdir, subsubdirs, filename, - boost::bind(push_back, boost::ref(results), _2)); - } - else // CURRENT_SKIN - { - // CURRENT_SKIN turns out to be a bit of a misnomer because we might - // still return files from two different skins. In any case, this - // value of 'constraint' means we will return at most two paths: one - // for the default language, one for the current language (supposing - // those differ). - // It is important to allow a user to override only the localization - // for a particular file, for all viewer installs, without also - // overriding the default-language file. - // It is important to allow a user to override only the default- - // language file, for all viewer installs, without also overriding the - // applicable localization of that file. - // Therefore, treat the default language and the current language as - // two separate cases. For each, capture the most-specialized file - // that exists. - // Use a map keyed by subsubdir (i.e. language code). This allows us - // to handle the case of a single subsubdirs entry with the same logic - // that handles two. For every real file path generated by - // walkSearchSkinDirs(), update the map entry for its subsubdir. - StringMap path_for; - walkSearchSkinDirs(subdir, subsubdirs, filename, - boost::bind(store_in_map, boost::ref(path_for), _1, _2)); - // Now that we have a path for each of the default language and the - // current language, copy them -- in proper order -- into results. - // Don't drive this by walking the map itself: it matters that we - // generate results in the same order as subsubdirs. - BOOST_FOREACH(std::string subsubdir, subsubdirs) - { - StringMap::const_iterator found(path_for.find(subsubdir)); - if (found != path_for.end()) - { - results.push_back(found->second); - } - } - } - - LL_DEBUGS("LLDir") << empty; - const char* comma = ""; - BOOST_FOREACH(std::string path, results) - { - LL_CONT << comma << "'" << path << "'"; - comma = ", "; - } - LL_CONT << LL_ENDL; - - return results; -} - -std::string LLDir::getTempFilename() const -{ - LLUUID random_uuid; - std::string uuid_str; - - random_uuid.generate(); - random_uuid.toString(uuid_str); - - return add(getTempDir(), uuid_str + ".tmp"); -} - -// static -std::string LLDir::getScrubbedFileName(const std::string uncleanFileName) -{ - std::string name(uncleanFileName); - const std::string illegalChars(getForbiddenFileChars()); - // replace any illegal file chars with and underscore '_' - for( unsigned int i = 0; i < illegalChars.length(); i++ ) - { - int j = -1; - while((j = name.find(illegalChars[i])) > -1) - { - name[j] = '_'; - } - } - return name; -} - -// static -std::string LLDir::getForbiddenFileChars() -{ - return "\\/:*?\"<>|"; -} - -void LLDir::setLindenUserDir(const std::string &username) -{ - // if the username isn't set, that's bad - if (!username.empty()) - { - // some platforms have case-sensitive filesystems, so be - // utterly consistent with our firstname/lastname case. - std::string userlower(username); - LLStringUtil::toLower(userlower); - LLStringUtil::replaceChar(userlower, ' ', '_'); - mLindenUserDir = add(getOSUserAppDir(), userlower); - } - else - { - LL_ERRS() << "NULL name for LLDir::setLindenUserDir" << LL_ENDL; - } - - dumpCurrentDirectories(); -} - -void LLDir::setChatLogsDir(const std::string &path) -{ - if (!path.empty() ) - { - mChatLogsDir = path; - } - else - { - LL_WARNS() << "Invalid name for LLDir::setChatLogsDir" << LL_ENDL; - } -} - -void LLDir::updatePerAccountChatLogsDir() -{ - mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName); -} - -void LLDir::setPerAccountChatLogsDir(const std::string &username) -{ - // if both first and last aren't set, assume we're grabbing the cached dir - if (!username.empty()) - { - // some platforms have case-sensitive filesystems, so be - // utterly consistent with our firstname/lastname case. - std::string userlower(username); - LLStringUtil::toLower(userlower); - LLStringUtil::replaceChar(userlower, ' ', '_'); - - mUserName = userlower; - updatePerAccountChatLogsDir(); - } - else - { - LL_ERRS() << "NULL name for LLDir::setPerAccountChatLogsDir" << LL_ENDL; - } -} - -void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language) -{ - LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'" - << LL_ENDL; - mSkinName = skin_folder; - mLanguage = language; - - // This method is called multiple times during viewer initialization. Each - // time it's called, reset mSearchSkinDirs. - mSearchSkinDirs.clear(); - - // base skin which is used as fallback for all skinned files - // e.g. c:\program files\secondlife\skins\default - mDefaultSkinDir = getSkinBaseDir(); - append(mDefaultSkinDir, "default"); - // This is always the most general of the search skin directories. - addSearchSkinDir(mDefaultSkinDir); - - mSkinDir = getSkinBaseDir(); - append(mSkinDir, skin_folder); - // Next level of generality is a skin installed with the viewer. - addSearchSkinDir(mSkinDir); - - // user modifications to skins, current and default - // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle - mUserSkinDir = getOSUserAppDir(); - append(mUserSkinDir, "skins"); - mUserDefaultSkinDir = mUserSkinDir; - append(mUserDefaultSkinDir, "default"); - append(mUserSkinDir, skin_folder); - // Next level of generality is user modifications to default skin... - addSearchSkinDir(mUserDefaultSkinDir); - // then user-defined skins. - addSearchSkinDir(mUserSkinDir); -} - -void LLDir::addSearchSkinDir(const std::string& skindir) -{ - if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end()) - { - LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL; - mSearchSkinDirs.push_back(skindir); - } -} - -std::string LLDir::getSkinFolder() const -{ - return mSkinName; -} - -std::string LLDir::getLanguage() const -{ - return mLanguage; -} - -bool LLDir::setCacheDir(const std::string &path) -{ - if (path.empty() ) - { - // reset to default - mCacheDir = ""; - return true; - } - else - { - LLFile::mkdir(path); - std::string tempname = add(path, "temp"); - LLFILE* file = LLFile::fopen(tempname,"wt"); - if (file) - { - fclose(file); - LLFile::remove(tempname); - mCacheDir = path; - return true; - } - return false; - } -} - -void LLDir::dumpCurrentDirectories(LLError::ELevel level) -{ - LL_VLOGS(level, "AppInit","Directories") << "Current Directories:" << LL_ENDL; - - LL_VLOGS(level, "AppInit", "Directories") << " CurPath: " << getCurPath() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " AppName: " << getAppName() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " ExecutableFilename: " << getExecutableFilename() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " ExecutableDir: " << getExecutableDir() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " ExecutablePathAndName: " << getExecutablePathAndName() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " WorkingDir: " << getWorkingDir() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " AppRODataDir: " << getAppRODataDir() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " OSUserDir: " << getOSUserDir() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " OSUserAppDir: " << getOSUserAppDir() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " TempDir: " << getTempDir() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " CAFile: " << getCAFile() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL; - LL_VLOGS(level, "AppInit", "Directories") << " SkinDir: " << getSkinDir() << LL_ENDL; -} - -void LLDir::append(std::string& destpath, const std::string& name) const -{ - // Delegate question of whether we need a separator to helper method. - SepOff sepoff(needSep(destpath, name)); - if (sepoff.first) // do we need a separator? - { - destpath += mDirDelimiter; - } - // If destpath ends with a separator, AND name starts with one, skip - // name's leading separator. - destpath += name.substr(sepoff.second); -} - -LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) const -{ - if (path.empty() || name.empty()) - { - // If either path or name are empty, we do not need a separator - // between them. - return SepOff(false, 0); - } - // Here we know path and name are both non-empty. But if path already ends - // with a separator, or if name already starts with a separator, we need - // not add one. - std::string::size_type seplen(mDirDelimiter.length()); - bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter); - bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter); - if ((! path_ends_sep) && (! name_starts_sep)) - { - // If neither path nor name brings a separator to the junction, then - // we need one. - return SepOff(true, 0); - } - if (path_ends_sep && name_starts_sep) - { - // But if BOTH path and name bring a separator, we need not add one. - // Moreover, we should actually skip the leading separator of 'name'. - return SepOff(false, (unsigned short)seplen); - } - // Here we know that either path_ends_sep or name_starts_sep is true -- - // but not both. So don't add a separator, and don't skip any characters: - // simple concatenation will do the trick. - return SepOff(false, 0); -} - -void dir_exists_or_crash(const std::string &dir_name) -{ -#if LL_WINDOWS - // *FIX: lame - it doesn't do the same thing on windows. not so - // important since we don't deploy simulator to windows boxes. - LLFile::mkdir(dir_name, 0700); -#else - struct stat dir_stat; - if(0 != LLFile::stat(dir_name, &dir_stat)) - { - S32 stat_rv = errno; - if(ENOENT == stat_rv) - { - if(0 != LLFile::mkdir(dir_name, 0700)) // octal - { - LL_ERRS() << "Unable to create directory: " << dir_name << LL_ENDL; - } - } - else - { - LL_ERRS() << "Unable to stat: " << dir_name << " errno = " << stat_rv - << LL_ENDL; - } - } - else - { - // data_dir exists, make sure it's a directory. - if(!S_ISDIR(dir_stat.st_mode)) - { - LL_ERRS() << "Data directory collision: " << dir_name << LL_ENDL; - } - } -#endif -} diff --git a/indra/llcache/lldir.h b/indra/llcache/lldir.h deleted file mode 100644 index 38e204ef04..0000000000 --- a/indra/llcache/lldir.h +++ /dev/null @@ -1,280 +0,0 @@ -/** - * @file lldir.h - * @brief Definition of directory utilities class - * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLDIR_H -#define LL_LLDIR_H - -#if LL_SOLARIS -#include -#define MAX_PATH MAXPATHLEN -#endif - -// these numbers are read from settings_files.xml, so we need to be explicit -typedef enum ELLPath -{ - LL_PATH_NONE = 0, - LL_PATH_USER_SETTINGS = 1, - LL_PATH_APP_SETTINGS = 2, - LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet - LL_PATH_CACHE = 4, - LL_PATH_CHARACTER = 5, - LL_PATH_HELP = 6, - LL_PATH_LOGS = 7, - LL_PATH_TEMP = 8, - LL_PATH_SKINS = 9, - LL_PATH_TOP_SKIN = 10, - LL_PATH_CHAT_LOGS = 11, - LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12, - LL_PATH_USER_SKIN = 14, - LL_PATH_LOCAL_ASSETS = 15, - LL_PATH_EXECUTABLE = 16, - LL_PATH_DEFAULT_SKIN = 17, - LL_PATH_FONTS = 18, - LL_PATH_DUMP = 19, - LL_PATH_LAST -} ELLPath; - -/// Directory operations -class LLDir -{ - public: - LLDir(); - virtual ~LLDir(); - - // app_name - Usually SecondLife, used for creating settings directories - // in OS-specific location, such as C:\Documents and Settings - // app_read_only_data_dir - Usually the source code directory, used - // for test applications to read newview data files. - virtual void initAppDirs(const std::string &app_name, - const std::string& app_read_only_data_dir = "") = 0; - - virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask); - U32 deleteDirAndContents(const std::string& dir_name); - std::vector getFilesInDir(const std::string &dirname); -// pure virtual functions - virtual std::string getCurPath() = 0; - virtual bool fileExists(const std::string &filename) const = 0; - - 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; - - virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell - virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so') - - const std::string &getExecutablePathAndName() const; // Full pathname of the executable - const std::string &getAppName() const; // install directory under progams/ ie "SecondLife" - const std::string &getExecutableDir() const; // Directory where the executable is located - const std::string &getExecutableFilename() const;// Filename of .exe - const std::string &getWorkingDir() const; // Current working directory - const std::string &getAppRODataDir() const; // Location of read-only data files - const std::string &getOSUserDir() const; // Location of the os-specific user dir - const std::string &getOSUserAppDir() const; // Location of the os-specific user app dir - const std::string &getLindenUserDir() const; // Location of the Linden user dir. - const std::string &getChatLogsDir() const; // Location of the chat logs dir. - const std::string &getDumpDir() const; // Location of the per-run dump dir. - const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir. - const std::string &getTempDir() const; // Common temporary directory - const std::string getCacheDir(bool get_default = false) const; // Location of the cache. - const std::string &getOSCacheDir() const; // location of OS-specific cache folder (may be empty string) - const std::string &getCAFile() const; // File containing TLS certificate authorities - const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':') - const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default - const std::string &getSkinDir() const; // User-specified skin folder. - const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin - const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin - const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins - const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell - const std::string &getUserName() const; - - // Expanded filename - std::string getExpandedFilename(ELLPath location, const std::string &filename) const; - std::string getExpandedFilename(ELLPath location, const std::string &subdir, const std::string &filename) const; - std::string getExpandedFilename(ELLPath location, const std::string &subdir1, const std::string &subdir2, const std::string &filename) const; - - // Base and Directory name extraction - std::string getBaseFileName(const std::string& filepath, bool strip_exten = false) const; - std::string getDirName(const std::string& filepath) const; - std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav" - - // these methods search the various skin paths for the specified file in the following order: - // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir() - /// param value for findSkinnedFilenames(), explained below - enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS }; - /** - * Given a filename within skin, return an ordered sequence of paths to - * search. Nonexistent files will be filtered out -- which means that the - * vector might be empty. - * - * @param subdir Identify top-level skin subdirectory by passing one of - * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file - * lives under "textures" subtree), LLDir::SKINBASE (file lives at top - * level of skin subdirectory). - * @param filename Desired filename within subdir within skin, e.g. - * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language. - * @param constraint Callers perform two different kinds of processing. - * When fetching a XUI file, for instance, the existence of @a filename in - * the specified skin completely supercedes any @a filename in the default - * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The - * returned vector will contain only - * ".../current_skin/xui/en/filename", - * ".../current_skin/xui/current_language/filename". - * But for (e.g.) "strings.xml", we want a given skin to be able to - * override only specific entries from the default skin. Any string not - * defined in the specified skin will be sought in the default skin. For - * that case, pass @a constraint=ALL_SKINS. The returned vector will - * contain at least ".../default/xui/en/strings.xml", - * ".../default/xui/current_language/strings.xml", - * ".../current_skin/xui/en/strings.xml", - * ".../current_skin/xui/current_language/strings.xml". - */ - std::vector findSkinnedFilenames(const std::string& subdir, - const std::string& filename, - ESkinConstraint constraint=CURRENT_SKIN) const; - /// Values for findSkinnedFilenames(subdir) parameter - static const char *XUI, *TEXTURES, *SKINBASE; - /** - * Return the base-language pathname from findSkinnedFilenames(), or - * the empty string if no such file exists. Parameters are identical to - * findSkinnedFilenames(). This is shorthand for capturing the vector - * returned by findSkinnedFilenames(), checking for empty() and then - * returning front(). - */ - std::string findSkinnedFilenameBaseLang(const std::string &subdir, - const std::string &filename, - ESkinConstraint constraint=CURRENT_SKIN) const; - /** - * Return the "most localized" pathname from findSkinnedFilenames(), or - * the empty string if no such file exists. Parameters are identical to - * findSkinnedFilenames(). This is shorthand for capturing the vector - * returned by findSkinnedFilenames(), checking for empty() and then - * returning back(). - */ - std::string findSkinnedFilename(const std::string &subdir, - const std::string &filename, - ESkinConstraint constraint=CURRENT_SKIN) const; - - // random filename in common temporary directory - std::string getTempFilename() const; - - // For producing safe download file names from potentially unsafe ones - static std::string getScrubbedFileName(const std::string uncleanFileName); - static std::string getForbiddenFileChars(); - void setDumpDir( const std::string& path ); - - - virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir - virtual void setPerAccountChatLogsDir(const std::string &username); // Set the per user chat log directory. - virtual void setLindenUserDir(const std::string &username); // Set the linden user dir to this user's dir - virtual void setSkinFolder(const std::string &skin_folder, const std::string& language); - virtual std::string getSkinFolder() const; - virtual std::string getLanguage() const; - virtual bool setCacheDir(const std::string &path); - virtual void updatePerAccountChatLogsDir(); - - virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG); - - // Utility routine - std::string buildSLOSCacheDir() const; - - /// Append specified @a name to @a destpath, separated by getDirDelimiter() - /// if both are non-empty. - void append(std::string& destpath, const std::string& name) const; - /// Variadic form: append @a name0 and @a name1 and arbitrary other @a - /// names to @a destpath, separated by getDirDelimiter() as needed. - template - void append(std::string& destpath, const std::string& name0, const std::string& name1, - const NAMES& ... names) const - { - // In a typical recursion case, we'd accept (destpath, name0, names). - // We accept (destpath, name0, name1, names) because it's important to - // delegate the two-argument case to the non-template implementation. - append(destpath, name0); - append(destpath, name1, names...); - } - - /// Append specified @a names to @a path, separated by getDirDelimiter() - /// as needed. Return result, leaving @a path unmodified. - template - std::string add(const std::string& path, const NAMES& ... names) const - { - std::string destpath(path); - append(destpath, names...); - return destpath; - } - -protected: - // Does an add() or append() call need a directory delimiter? - typedef std::pair SepOff; - SepOff needSep(const std::string& path, const std::string& name) const; - // build mSearchSkinDirs without adding duplicates - void addSearchSkinDir(const std::string& skindir); - - // Internal to findSkinnedFilenames() - template - void walkSearchSkinDirs(const std::string& subdir, - const std::vector& subsubdirs, - const std::string& filename, - const FUNCTION& function) const; - - std::string mAppName; // install directory under progams/ ie "SecondLife" - std::string mExecutablePathAndName; // full path + Filename of .exe - std::string mExecutableFilename; // Filename of .exe - std::string mExecutableDir; // Location of executable - std::string mWorkingDir; // Current working directory - std::string mAppRODataDir; // Location for static app data - std::string mOSUserDir; // OS Specific user directory - std::string mOSUserAppDir; // OS Specific user app directory - std::string mLindenUserDir; // Location for Linden user-specific data - std::string mPerAccountChatLogsDir; // Location for chat logs. - std::string mChatLogsDir; // Location for chat logs. - std::string mCAFile; // Location of the TLS certificate authority PEM file. - std::string mTempDir; - std::string mCacheDir; // cache directory as set by user preference - std::string mDefaultCacheDir; // default cache diretory - std::string mOSCacheDir; // operating system cache dir - std::string mDirDelimiter; - std::string mSkinName; // caller-specified skin name - std::string mSkinBaseDir; // Base for skins paths. - std::string mDefaultSkinDir; // Location for default skin info. - std::string mSkinDir; // Location for current skin info. - std::string mUserDefaultSkinDir; // Location for default skin info. - std::string mUserSkinDir; // Location for user-modified skin info. - // Skin directories to search, most general to most specific. This order - // works well for composing fine-grained files, in which an individual item - // in a specific file overrides the corresponding item in more general - // files. Of course, for a file-level search, iterate backwards. - std::vector mSearchSkinDirs; - std::string mLanguage; // Current viewer language - std::string mLLPluginDir; // Location for plugins and plugin shell - static std::string sDumpDir; // Per-run crash report subdir of log directory. - std::string mUserName; // Current user name -}; - -void dir_exists_or_crash(const std::string &dir_name); - -extern LLDir *gDirUtilp; - -#endif // LL_LLDIR_H diff --git a/indra/llcache/lldir_linux.cpp b/indra/llcache/lldir_linux.cpp deleted file mode 100644 index 80ad05345a..0000000000 --- a/indra/llcache/lldir_linux.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/** - * @file lldir_linux.cpp - * @brief Implementation of directory utilities for linux - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "lldir_linux.h" -#include "llerror.h" -#include "llrand.h" -#include "llstring.h" -#include -#include -#include -#include -#include - - -static std::string getCurrentUserHome(char* fallback) -{ - const uid_t uid = getuid(); - struct passwd *pw; - - pw = getpwuid(uid); - if ((pw != NULL) && (pw->pw_dir != NULL)) - { - return pw->pw_dir; - } - - LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL; - auto home_env = LLStringUtil::getoptenv("HOME"); - if (home_env) - { - return *home_env; - } - else - { - LL_WARNS() << "Couldn't detect home directory! Falling back to " << fallback << LL_ENDL; - return fallback; - } -} - - -LLDir_Linux::LLDir_Linux() -{ - mDirDelimiter = "/"; - mCurrentDirIndex = -1; - mCurrentDirCount = -1; - mDirp = NULL; - - char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ - if (getcwd(tmp_str, LL_MAX_PATH) == NULL) - { - strcpy(tmp_str, "/tmp"); - LL_WARNS() << "Could not get current directory; changing to " - << tmp_str << LL_ENDL; - if (chdir(tmp_str) == -1) - { - LL_ERRS() << "Could not change directory to " << tmp_str << LL_ENDL; - } - } - - mExecutableFilename = ""; - mExecutablePathAndName = ""; - mExecutableDir = tmp_str; - mWorkingDir = tmp_str; -#ifdef APP_RO_DATA_DIR - mAppRODataDir = APP_RO_DATA_DIR; -#else - mAppRODataDir = tmp_str; -#endif - std::string::size_type build_dir_pos = mExecutableDir.rfind("/build-linux-"); - if (build_dir_pos != std::string::npos) - { - // ...we're in a dev checkout - mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "/indra/newview/skins"; - LL_INFOS() << "Running in dev checkout with mSkinBaseDir " - << mSkinBaseDir << LL_ENDL; - } - else - { - // ...normal installation running - mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; - } - - mOSUserDir = getCurrentUserHome(tmp_str); - mOSUserAppDir = ""; - mLindenUserDir = ""; - - char path [32]; /* Flawfinder: ignore */ - - // *NOTE: /proc/%d/exe doesn't work on FreeBSD. But that's ok, - // because this is the linux implementation. - - snprintf (path, sizeof(path), "/proc/%d/exe", (int) getpid ()); - int rc = readlink (path, tmp_str, sizeof (tmp_str)-1); /* Flawfinder: ignore */ - if ( (rc != -1) && (rc <= ((int) sizeof (tmp_str)-1)) ) - { - tmp_str[rc] = '\0'; //readlink() doesn't 0-terminate the buffer - mExecutablePathAndName = tmp_str; - char *path_end; - if ((path_end = strrchr(tmp_str,'/'))) - { - *path_end = '\0'; - mExecutableDir = tmp_str; - mWorkingDir = tmp_str; - mExecutableFilename = path_end+1; - } - else - { - mExecutableFilename = tmp_str; - } - } - - mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin"; - - // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. - mTempDir = "/tmp"; -} - -LLDir_Linux::~LLDir_Linux() -{ -} - -// Implementation - - -void LLDir_Linux::initAppDirs(const std::string &app_name, - const std::string& app_read_only_data_dir) -{ - // Allow override so test apps can read newview directory - if (!app_read_only_data_dir.empty()) - { - mAppRODataDir = app_read_only_data_dir; - mSkinBaseDir = add(mAppRODataDir, "skins"); - } - mAppName = app_name; - - std::string upper_app_name(app_name); - LLStringUtil::toUpper(upper_app_name); - - auto app_home_env(LLStringUtil::getoptenv(upper_app_name + "_USER_DIR")); - if (app_home_env) - { - // user has specified own userappdir i.e. $SECONDLIFE_USER_DIR - mOSUserAppDir = *app_home_env; - } - else - { - // traditionally on unixoids, MyApp gets ~/.myapp dir for data - mOSUserAppDir = mOSUserDir; - mOSUserAppDir += "/"; - mOSUserAppDir += "."; - std::string lower_app_name(app_name); - LLStringUtil::toLower(lower_app_name); - mOSUserAppDir += lower_app_name; - } - - // create any directories we expect to write to. - - int res = LLFile::mkdir(mOSUserAppDir); - if (res == -1) - { - LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL; - LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL; - mOSUserAppDir = mOSUserDir; - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"")); - if (res == -1) - { - LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL; - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"")); - if (res == -1) - { - LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL; - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"")); - if (res == -1) - { - LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; - } - - mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "ca-bundle.crt"); -} - -U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string &mask) -{ - U32 file_count = 0; - glob_t g; - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - file_count = g.gl_pathc; - - globfree(&g); - } - - return (file_count); -} - -std::string LLDir_Linux::getCurPath() -{ - char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ - if (getcwd(tmp_str, LL_MAX_PATH) == NULL) - { - LL_WARNS() << "Could not get current directory" << LL_ENDL; - tmp_str[0] = '\0'; - } - 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() + - "SLPlugin"; -} - -/*virtual*/ std::string LLDir_Linux::getLLPluginFilename(std::string base_name) -{ - return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + - "lib" + base_name + ".so"; -} diff --git a/indra/llcache/lldir_linux.h b/indra/llcache/lldir_linux.h deleted file mode 100644 index e83a020ba4..0000000000 --- a/indra/llcache/lldir_linux.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file lldir_linux.h - * @brief Definition of directory utilities class for linux - * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if !LL_LINUX -#error This header must not be included when compiling for any target other than Linux. Consider including lldir.h instead. -#endif // !LL_LINUX - -#ifndef LL_LLDIR_LINUX_H -#define LL_LLDIR_LINUX_H - -#include "lldir.h" - -#include -#include - -class LLDir_Linux : public LLDir -{ -public: - LLDir_Linux(); - virtual ~LLDir_Linux(); - - /*virtual*/ void initAppDirs(const std::string &app_name, - const std::string& app_read_only_data_dir); - - 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); - -private: - DIR *mDirp; - int mCurrentDirIndex; - int mCurrentDirCount; - std::string mCurrentDir; -}; - -#endif // LL_LLDIR_LINUX_H - - diff --git a/indra/llcache/lldir_mac.cpp b/indra/llcache/lldir_mac.cpp deleted file mode 100644 index 3bc4ee844e..0000000000 --- a/indra/llcache/lldir_mac.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/** - * @file lldir_mac.cpp - * @brief Implementation of directory utilities for Mac OS X - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if LL_DARWIN - -#include "linden_common.h" - -#include "lldir_mac.h" -#include "llerror.h" -#include "llrand.h" -#include -#include -#include -#include -#include -#include "lldir_utils_objc.h" - -// -------------------------------------------------------------------------------- - -static bool CreateDirectory(const std::string &parent, - const std::string &child, - std::string *fullname) -{ - - boost::filesystem::path p(parent); - p /= child; - - if (fullname) - *fullname = std::string(p.string()); - - if (! boost::filesystem::create_directory(p)) - { - return (boost::filesystem::is_directory(p)); - } - return true; -} - -// -------------------------------------------------------------------------------- - -LLDir_Mac::LLDir_Mac() -{ - mDirDelimiter = "/"; - - const std::string secondLifeString = "SecondLife"; - - std::string *executablepathstr = getSystemExecutableFolder(); - - //NOTE: LLINFOS/LLERRS will not output to log here. The streams are not initialized. - - if (executablepathstr) - { - // mExecutablePathAndName - mExecutablePathAndName = *executablepathstr; - - boost::filesystem::path executablepath(*executablepathstr); - -# ifndef BOOST_SYSTEM_NO_DEPRECATED -#endif - mExecutableFilename = executablepath.filename().string(); - mExecutableDir = executablepath.parent_path().string(); - - // mAppRODataDir - std::string *resourcepath = getSystemResourceFolder(); - mAppRODataDir = *resourcepath; - - // *NOTE: When running in a dev tree, use the copy of - // skins in indra/newview/ rather than in the application bundle. This - // mirrors Windows dev environment behavior and allows direct checkin - // of edited skins/xui files. JC - - // MBW -- This keeps the mac application from finding other things. - // If this is really for skins, it should JUST apply to skins. - - std::string::size_type build_dir_pos = mExecutableDir.rfind("/build-darwin-"); - if (build_dir_pos != std::string::npos) - { - // ...we're in a dev checkout - mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) - + "/indra/newview/skins"; - LL_INFOS() << "Running in dev checkout with mSkinBaseDir " - << mSkinBaseDir << LL_ENDL; - } - else - { - // ...normal installation running - mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; - } - - // mOSUserDir - std::string *appdir = getSystemApplicationSupportFolder(); - std::string rootdir; - - //Create root directory - if (CreateDirectory(*appdir, secondLifeString, &rootdir)) - { - - // Save the full path to the folder - mOSUserDir = rootdir; - - // Create our sub-dirs - CreateDirectory(rootdir, std::string("data"), NULL); - CreateDirectory(rootdir, std::string("logs"), NULL); - CreateDirectory(rootdir, std::string("user_settings"), NULL); - CreateDirectory(rootdir, std::string("browser_profile"), NULL); - } - - //mOSCacheDir - std::string *cachedir = getSystemCacheFolder(); - - if (cachedir) - - { - mOSCacheDir = *cachedir; - //TODO: This changes from ~/Library/Cache/Secondlife to ~/Library/Cache/com.app.secondlife/Secondlife. Last dir level could go away. - CreateDirectory(mOSCacheDir, secondLifeString, NULL); - } - - // mOSUserAppDir - mOSUserAppDir = mOSUserDir; - - // mTempDir - //Aura 120920 boost::filesystem::temp_directory_path() not yet implemented on mac. :( - std::string *tmpdir = getSystemTempFolder(); - if (tmpdir) - { - - CreateDirectory(*tmpdir, secondLifeString, &mTempDir); - if (tmpdir) delete tmpdir; - } - - mWorkingDir = getCurPath(); - - mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin"; - } -} - -LLDir_Mac::~LLDir_Mac() -{ -} - -// Implementation - - -void LLDir_Mac::initAppDirs(const std::string &app_name, - const std::string& app_read_only_data_dir) -{ - // Allow override so test apps can read newview directory - if (!app_read_only_data_dir.empty()) - { - mAppRODataDir = app_read_only_data_dir; - mSkinBaseDir = add(mAppRODataDir, "skins"); - } - mCAFile = add(mAppRODataDir, "ca-bundle.crt"); -} - -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() + - "SLPlugin.app/Contents/MacOS/SLPlugin"; -} - -/*virtual*/ std::string LLDir_Mac::getLLPluginFilename(std::string base_name) -{ - return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + - base_name + ".dylib"; -} - - -#endif // LL_DARWIN diff --git a/indra/llcache/lldir_mac.h b/indra/llcache/lldir_mac.h deleted file mode 100644 index 558727ebbc..0000000000 --- a/indra/llcache/lldir_mac.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file lldir_mac.h - * @brief Definition of directory utilities class for Mac OS X - * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if !LL_DARWIN -#error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead. -#endif // !LL_DARWIN - -#ifndef LL_LLDIR_MAC_H -#define LL_LLDIR_MAC_H - -#include "lldir.h" - -#include - -class LLDir_Mac : public LLDir -{ -public: - LLDir_Mac(); - virtual ~LLDir_Mac(); - - /*virtual*/ void initAppDirs(const std::string &app_name, - 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); -}; - -#endif // LL_LLDIR_MAC_H - - diff --git a/indra/llcache/lldir_solaris.cpp b/indra/llcache/lldir_solaris.cpp deleted file mode 100644 index f18560ff20..0000000000 --- a/indra/llcache/lldir_solaris.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/** - * @file fmodwrapper.cpp - * @brief dummy source file for building a shared library to wrap libfmod.a - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "lldir_solaris.h" -#include "llerror.h" -#include "llrand.h" -#include "llstring.h" -#include -#include -#include -#include -#include -#include -#define _STRUCTURED_PROC 1 -#include -#include - -static std::string getCurrentUserHome(char* fallback) -{ - // fwiw this exactly duplicates getCurrentUserHome() in lldir_linux.cpp... - // we should either derive both from LLDir_Posix or just axe Solaris. - const uid_t uid = getuid(); - struct passwd *pw; - - pw = getpwuid(uid); - if ((pw != NULL) && (pw->pw_dir != NULL)) - { - return pw->pw_dir; - } - - LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL; - auto home_env = LLStringUtil::getoptenv("HOME"); - if (home_env) - { - return *home_env; - } - else - { - LL_WARNS() << "Couldn't detect home directory! Falling back to " << fallback << LL_ENDL; - return fallback; - } -} - - -LLDir_Solaris::LLDir_Solaris() -{ - mDirDelimiter = "/"; - mCurrentDirIndex = -1; - mCurrentDirCount = -1; - mDirp = NULL; - - char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ - if (getcwd(tmp_str, LL_MAX_PATH) == NULL) - { - strcpy(tmp_str, "/tmp"); - LL_WARNS() << "Could not get current directory; changing to " - << tmp_str << LL_ENDL; - if (chdir(tmp_str) == -1) - { - LL_ERRS() << "Could not change directory to " << tmp_str << LL_ENDL; - } - } - - mExecutableFilename = ""; - mExecutablePathAndName = ""; - mExecutableDir = strdup(tmp_str); - mWorkingDir = strdup(tmp_str); - mAppRODataDir = strdup(tmp_str); - mOSUserDir = getCurrentUserHome(tmp_str); - mOSUserAppDir = ""; - mLindenUserDir = ""; - - char path [LL_MAX_PATH]; /* Flawfinder: ignore */ - - sprintf(path, "/proc/%d/psinfo", (int)getpid()); - int proc_fd = -1; - if((proc_fd = open(path, O_RDONLY)) == -1){ - LL_WARNS() << "unable to open " << path << LL_ENDL; - return; - } - psinfo_t proc_psinfo; - if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){ - LL_WARNS() << "Unable to read " << path << LL_ENDL; - close(proc_fd); - return; - } - - close(proc_fd); - - mExecutableFilename = strdup(proc_psinfo.pr_fname); - LL_INFOS() << "mExecutableFilename = [" << mExecutableFilename << "]" << LL_ENDL; - - sprintf(path, "/proc/%d/path/a.out", (int)getpid()); - - char execpath[LL_MAX_PATH]; - if(readlink(path, execpath, LL_MAX_PATH) == -1){ - LL_WARNS() << "Unable to read link from " << path << LL_ENDL; - return; - } - - char *p = execpath; // nuke trash in link, if any exists - int i = 0; - while(*p != NULL && ++i < LL_MAX_PATH && isprint((int)(*p++))); - *p = NULL; - - mExecutablePathAndName = strdup(execpath); - LL_INFOS() << "mExecutablePathAndName = [" << mExecutablePathAndName << "]" << LL_ENDL; - - //NOTE: Why force people to cd into the package directory? - // Look for SECONDLIFE env variable and use it, if set. - - auto SECONDLIFE(LLDirUtil::getoptenv("SECONDLIFE")); - if(SECONDLIFE){ - mExecutableDir = add(*SECONDLIFE, "bin"); //NOTE: make sure we point at the bin - }else{ - mExecutableDir = getDirName(execpath); - LL_INFOS() << "mExecutableDir = [" << mExecutableDir << "]" << LL_ENDL; - } - - mLLPluginDir = add(mExecutableDir, "llplugin"); - - // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. - mTempDir = "/tmp"; -} - -LLDir_Solaris::~LLDir_Solaris() -{ -} - -// Implementation - - -void LLDir_Solaris::initAppDirs(const std::string &app_name, - const std::string& app_read_only_data_dir) -{ - // Allow override so test apps can read newview directory - if (!app_read_only_data_dir.empty()) - { - mAppRODataDir = app_read_only_data_dir; - mSkinBaseDir = add(mAppRODataDir, "skins"); - } - mAppName = app_name; - - std::string upper_app_name(app_name); - LLStringUtil::toUpper(upper_app_name); - - auto app_home_env(LLStringUtil::getoptenv(upper_app_name + "_USER_DIR")); - if (app_home_env) - { - // user has specified own userappdir i.e. $SECONDLIFE_USER_DIR - mOSUserAppDir = *app_home_env; - } - else - { - // traditionally on unixoids, MyApp gets ~/.myapp dir for data - mOSUserAppDir = mOSUserDir; - mOSUserAppDir += "/"; - mOSUserAppDir += "."; - std::string lower_app_name(app_name); - LLStringUtil::toLower(lower_app_name); - mOSUserAppDir += lower_app_name; - } - - // create any directories we expect to write to. - - int res = LLFile::mkdir(mOSUserAppDir); - if (res == -1) - { - LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL; - LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL; - mOSUserAppDir = mOSUserDir; - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"")); - if (res == -1) - { - LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL; - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"")); - if (res == -1) - { - LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL; - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"")); - if (res == -1) - { - LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; - } - - mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "ca-bundle.crt"); -} - -U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string &mask) -{ - U32 file_count = 0; - glob_t g; - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - file_count = g.gl_pathc; - - globfree(&g); - } - - return (file_count); -} - -std::string LLDir_Solaris::getCurPath() -{ - char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ - if (getcwd(tmp_str, LL_MAX_PATH) == NULL) - { - LL_WARNS() << "Could not get current directory" << LL_ENDL; - tmp_str[0] = '\0'; - } - return tmp_str; -} - - -bool LLDir_Solaris::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; - } -} - diff --git a/indra/llcache/lldir_solaris.h b/indra/llcache/lldir_solaris.h deleted file mode 100644 index c6dac57e14..0000000000 --- a/indra/llcache/lldir_solaris.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file fmodwrapper.cpp - * @brief dummy source file for building a shared library to wrap libfmod.a - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if !LL_SOLARIS -#error This header must not be included when compiling for any target other than Solaris. Consider including lldir.h instead. -#endif // !LL_SOLARIS - -#ifndef LL_LLDIR_SOLARIS_H -#define LL_LLDIR_SOLARIS_H - -#include "lldir.h" - -#include -#include - -class LLDir_Solaris : public LLDir -{ -public: - LLDir_Solaris(); - virtual ~LLDir_Solaris(); - - /*virtual*/ void initAppDirs(const std::string &app_name, - const std::string& app_read_only_data_dir); - - virtual std::string getCurPath(); - virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ bool fileExists(const std::string &filename) const; - -private: - DIR *mDirp; - int mCurrentDirIndex; - int mCurrentDirCount; - std::string mCurrentDir; -}; - -#endif // LL_LLDIR_SOLARIS_H - - diff --git a/indra/llcache/lldir_utils_objc.h b/indra/llcache/lldir_utils_objc.h deleted file mode 100644 index 12019c4284..0000000000 --- a/indra/llcache/lldir_utils_objc.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file lldir_utils_objc.h - * @brief Definition of directory utilities class for Mac OS X - * - * $LicenseInfo:firstyear=2020&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2020, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if !LL_DARWIN -#error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead. -#endif // !LL_DARWIN - -#ifndef LL_LLDIR_UTILS_OBJC_H -#define LL_LLDIR_UTILS_OBJC_H - -#include - -std::string* getSystemTempFolder(); -std::string* getSystemCacheFolder(); -std::string* getSystemApplicationSupportFolder(); -std::string* getSystemResourceFolder(); -std::string* getSystemExecutableFolder(); - - -#endif // LL_LLDIR_UTILS_OBJC_H diff --git a/indra/llcache/lldir_utils_objc.mm b/indra/llcache/lldir_utils_objc.mm deleted file mode 100644 index da55a2f897..0000000000 --- a/indra/llcache/lldir_utils_objc.mm +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file lldir_utils_objc.mm - * @brief Cocoa implementation of directory utilities for Mac OS X - * - * $LicenseInfo:firstyear=2020&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2020, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ -#if LL_DARWIN - -//WARNING: This file CANNOT use standard linden includes due to conflicts between definitions of BOOL - -#include "lldir_utils_objc.h" -#import - -std::string* getSystemTempFolder() -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSString * tempDir = NSTemporaryDirectory(); - if (tempDir == nil) - tempDir = @"/tmp"; - std::string *result = ( new std::string([tempDir UTF8String]) ); - [pool release]; - - return result; -} - -//findSystemDirectory scoped exclusively to this file. -std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory, - NSSearchPathDomainMask domainMask) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - std::string *result = nil; - NSString *path = nil; - - // Search for the path - NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory, - domainMask, - YES); - if ([paths count]) - { - path = [paths objectAtIndex:0]; - //HACK: Always attempt to create directory, ignore errors. - NSError *error = nil; - - [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error]; - - - result = new std::string([path UTF8String]); - } - [pool release]; - return result; -} - -std::string* getSystemExecutableFolder() -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *bundlePath = [[NSBundle mainBundle] executablePath]; - std::string *result = (new std::string([bundlePath UTF8String])); - [pool release]; - - return result; -} - -std::string* getSystemResourceFolder() -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *bundlePath = [[NSBundle mainBundle] resourcePath]; - std::string *result = (new std::string([bundlePath UTF8String])); - [pool release]; - - return result; -} - -std::string* getSystemCacheFolder() -{ - return findSystemDirectory (NSCachesDirectory, - NSUserDomainMask); -} - -std::string* getSystemApplicationSupportFolder() -{ - return findSystemDirectory (NSApplicationSupportDirectory, - NSUserDomainMask); - -} - -#endif // LL_DARWIN diff --git a/indra/llcache/lldir_win32.cpp b/indra/llcache/lldir_win32.cpp deleted file mode 100644 index b3b3afb37e..0000000000 --- a/indra/llcache/lldir_win32.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/** - * @file lldir_win32.cpp - * @brief Implementation of directory utilities for windows - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if LL_WINDOWS - -#include "linden_common.h" - -#include "lldir_win32.h" -#include "llerror.h" -#include "llstring.h" -#include "stringize.h" -#include "llfile.h" -#include -#include - -#include -#include -#include -#include - -// Utility stuff to get versions of the sh -#define PACKVERSION(major,minor) MAKELONG(minor,major) -DWORD GetDllVersion(LPCTSTR lpszDllName); - -namespace -{ // anonymous - enum class prst { INIT, OPEN, SKIP } state = prst::INIT; - // This is called so early that we can't count on static objects being - // properly constructed yet, so declare a pointer instead of an instance. - std::ofstream* prelogf = nullptr; - - void prelog(const std::string& message) - { - boost::optional prelog_name; - - switch (state) - { - case prst::INIT: - // assume we failed, until we succeed - state = prst::SKIP; - - prelog_name = LLStringUtil::getoptenv("PRELOG"); - if (! prelog_name) - // no PRELOG variable set, carry on - return; - prelogf = new llofstream(*prelog_name, std::ios_base::app); - if (! (prelogf && prelogf->is_open())) - // can't complain to anybody; how? - return; - // got the log file open, cool! - state = prst::OPEN; - (*prelogf) << "========================================================================" - << std::endl; - // fall through, don't break - - case prst::OPEN: - (*prelogf) << message << std::endl; - break; - - case prst::SKIP: - // either PRELOG isn't set, or we failed to open that pathname - break; - } - } -} // anonymous namespace - -#define PRELOG(expression) prelog(STRINGIZE(expression)) - -LLDir_Win32::LLDir_Win32() -{ - // set this first: used by append() and add() methods - mDirDelimiter = "\\"; - - WCHAR w_str[MAX_PATH]; - // Application Data is where user settings go. We rely on $APPDATA being - // correct. - auto APPDATA = LLStringUtil::getoptenv("APPDATA"); - if (APPDATA) - { - mOSUserDir = *APPDATA; - } - PRELOG("APPDATA='" << mOSUserDir << "'"); - // On Windows, we could have received a plain-ASCII pathname in which - // non-ASCII characters have been munged to '?', or the pathname could - // have been badly encoded and decoded such that we now have garbage - // instead of a valid path. Check that mOSUserDir actually exists. - if (mOSUserDir.empty() || ! fileExists(mOSUserDir)) - { - PRELOG("APPDATA does not exist"); - //HRESULT okay = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, w_str); - wchar_t *pwstr = NULL; - HRESULT okay = SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &pwstr); - PRELOG("SHGetKnownFolderPath(FOLDERID_RoamingAppData) returned " << okay); - if (SUCCEEDED(okay) && pwstr) - { - // But of course, only update mOSUserDir if SHGetKnownFolderPath() works. - mOSUserDir = ll_convert_wide_to_string(pwstr); - // Not only that: update our environment so that child processes - // will see a reasonable value as well. - _wputenv_s(L"APPDATA", pwstr); - // SHGetKnownFolderPath() contract requires us to free pwstr - CoTaskMemFree(pwstr); - PRELOG("mOSUserDir='" << mOSUserDir << "'"); - } - } - - // We want cache files to go on the local disk, even if the - // user is on a network with a "roaming profile". - // - // On Vista this is: - // C:\Users\James\AppData\Local - // - // We used to store the cache in AppData\Roaming, and the installer - // cleans up that version on upgrade. JC - auto LOCALAPPDATA = LLStringUtil::getoptenv("LOCALAPPDATA"); - if (LOCALAPPDATA) - { - mOSCacheDir = *LOCALAPPDATA; - } - PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'"); - // Windows really does not deal well with pathnames containing non-ASCII - // characters. See above remarks about APPDATA. - if (mOSCacheDir.empty() || ! fileExists(mOSCacheDir)) - { - PRELOG("LOCALAPPDATA does not exist"); - //HRESULT okay = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, w_str); - wchar_t *pwstr = NULL; - HRESULT okay = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pwstr); - PRELOG("SHGetKnownFolderPath(FOLDERID_LocalAppData) returned " << okay); - if (SUCCEEDED(okay) && pwstr) - { - // But of course, only update mOSCacheDir if SHGetKnownFolderPath() works. - mOSCacheDir = ll_convert_wide_to_string(pwstr); - // Update our environment so that child processes will see a - // reasonable value as well. - _wputenv_s(L"LOCALAPPDATA", pwstr); - // SHGetKnownFolderPath() contract requires us to free pwstr - CoTaskMemFree(pwstr); - PRELOG("mOSCacheDir='" << mOSCacheDir << "'"); - } - } - - if (GetTempPath(MAX_PATH, w_str)) - { - if (wcslen(w_str)) /* Flawfinder: ignore */ - { - w_str[wcslen(w_str)-1] = '\0'; /* Flawfinder: ignore */ // remove trailing slash - } - mTempDir = utf16str_to_utf8str(llutf16string(w_str)); - - if (mOSUserDir.empty()) - { - mOSUserDir = mTempDir; - } - - if (mOSCacheDir.empty()) - { - mOSCacheDir = mTempDir; - } - } - else - { - mTempDir = mOSUserDir; - } - -/*==========================================================================*| - // Now that we've got mOSUserDir, one way or another, let's see how we did - // with our environment variables. - { - auto report = [this](std::ostream& out){ - out << "mOSUserDir = '" << mOSUserDir << "'\n" - << "mOSCacheDir = '" << mOSCacheDir << "'\n" - << "mTempDir = '" << mTempDir << "'" << std::endl; - }; - int res = LLFile::mkdir(mOSUserDir); - if (res == -1) - { - // If we couldn't even create the directory, just blurt to stderr - report(std::cerr); - } - else - { - // successfully created logdir, plunk a log file there - std::string logfilename(add(mOSUserDir, "lldir.log")); - std::ofstream logfile(logfilename.c_str()); - if (! logfile.is_open()) - { - report(std::cerr); - } - else - { - report(logfile); - } - } - } -|*==========================================================================*/ - -// fprintf(stderr, "mTempDir = <%s>",mTempDir); - - // Set working directory, for LLDir::getWorkingDir() - GetCurrentDirectory(MAX_PATH, w_str); - mWorkingDir = utf16str_to_utf8str(llutf16string(w_str)); - - // Set the executable directory - S32 size = GetModuleFileName(NULL, w_str, MAX_PATH); - if (size) - { - w_str[size] = '\0'; - mExecutablePathAndName = utf16str_to_utf8str(llutf16string(w_str)); - S32 path_end = mExecutablePathAndName.find_last_of('\\'); - if (path_end != std::string::npos) - { - mExecutableDir = mExecutablePathAndName.substr(0, path_end); - mExecutableFilename = mExecutablePathAndName.substr(path_end+1, std::string::npos); - } - else - { - mExecutableFilename = mExecutablePathAndName; - } - - } - else - { - fprintf(stderr, "Couldn't get APP path, assuming current directory!"); - mExecutableDir = mWorkingDir; - // Assume it's the current directory - } - - // mAppRODataDir = "."; - - // Determine the location of the App-Read-Only-Data - // Try the working directory then the exe's dir. - mAppRODataDir = mWorkingDir; - - -// if (mExecutableDir.find("indra") == std::string::npos) - - // *NOTE:Mani - It is a mistake to put viewer specific code in - // the LLDir implementation. The references to 'skins' and - // 'llplugin' need to go somewhere else. - // alas... this also gets called during static initialization - // time due to the construction of gDirUtil in lldir.cpp. - if(! LLFile::isdir(add(mAppRODataDir, "skins"))) - { - // What? No skins in the working dir? - // Try the executable's directory. - mAppRODataDir = mExecutableDir; - } - -// LL_INFOS() << "mAppRODataDir = " << mAppRODataDir << LL_ENDL; - - mSkinBaseDir = add(mAppRODataDir, "skins"); - - // Build the default cache directory - mDefaultCacheDir = buildSLOSCacheDir(); - - // Make sure it exists - int res = LLFile::mkdir(mDefaultCacheDir); - if (res == -1) - { - LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << mDefaultCacheDir << LL_ENDL; - } - - mLLPluginDir = add(mExecutableDir, "llplugin"); -} - -LLDir_Win32::~LLDir_Win32() -{ -} - -// Implementation - -void LLDir_Win32::initAppDirs(const std::string &app_name, - const std::string& app_read_only_data_dir) -{ - // Allow override so test apps can read newview directory - if (!app_read_only_data_dir.empty()) - { - mAppRODataDir = app_read_only_data_dir; - mSkinBaseDir = add(mAppRODataDir, "skins"); - } - mAppName = app_name; - mOSUserAppDir = add(mOSUserDir, app_name); - - int res = LLFile::mkdir(mOSUserAppDir); - if (res == -1) - { - LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL; - LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL; - mOSUserAppDir = mOSUserDir; - } - //dumpCurrentDirectories(); - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"")); - if (res == -1) - { - LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL; - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"")); - if (res == -1) - { - LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL; - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"")); - if (res == -1) - { - LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; - } - - mCAFile = getExpandedFilename( LL_PATH_EXECUTABLE, "ca-bundle.crt" ); -} - -U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &mask) -{ - HANDLE count_search_h; - U32 file_count; - - file_count = 0; - - WIN32_FIND_DATA FileData; - - llutf16string pathname = utf8str_to_utf16str(dirname); - pathname += utf8str_to_utf16str(mask); - - if ((count_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE) - { - file_count++; - - while (FindNextFile(count_search_h, &FileData)) - { - file_count++; - } - - FindClose(count_search_h); - } - - return (file_count); -} - -std::string LLDir_Win32::getCurPath() -{ - WCHAR w_str[MAX_PATH]; - GetCurrentDirectory(MAX_PATH, w_str); - - return utf16str_to_utf8str(llutf16string(w_str)); -} - - -bool LLDir_Win32::fileExists(const std::string &filename) const -{ - llstat stat_data; - // Check the age of the file - // Now, we see if the files we've gathered are recent... - int res = LLFile::stat(filename, &stat_data); - if (!res) - { - return TRUE; - } - else - { - return FALSE; - } -} - - -/*virtual*/ std::string LLDir_Win32::getLLPluginLauncher() -{ - return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + - "SLPlugin.exe"; -} - -/*virtual*/ std::string LLDir_Win32::getLLPluginFilename(std::string base_name) -{ - return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + - base_name + ".dll"; -} - - -#if 0 -// Utility function to get version number of a DLL - -#define PACKVERSION(major,minor) MAKELONG(minor,major) - -DWORD GetDllVersion(LPCTSTR lpszDllName) -{ - - HINSTANCE hinstDll; - DWORD dwVersion = 0; - - hinstDll = LoadLibrary(lpszDllName); /* Flawfinder: ignore */ - - if(hinstDll) - { - DLLGETVERSIONPROC pDllGetVersion; - - pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion"); - -/*Because some DLLs might not implement this function, you - must test for it explicitly. Depending on the particular - DLL, the lack of a DllGetVersion function can be a useful - indicator of the version. -*/ - if(pDllGetVersion) - { - DLLVERSIONINFO dvi; - HRESULT hr; - - ZeroMemory(&dvi, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - - hr = (*pDllGetVersion)(&dvi); - - if(SUCCEEDED(hr)) - { - dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion); - } - } - - FreeLibrary(hinstDll); - } - return dwVersion; -} -#endif - -#endif - - diff --git a/indra/llcache/lldir_win32.h b/indra/llcache/lldir_win32.h deleted file mode 100644 index 450efaf9da..0000000000 --- a/indra/llcache/lldir_win32.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file lldir_win32.h - * @brief Definition of directory utilities class for windows - * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if !LL_WINDOWS -#error This header must not be included when compiling for any target other than Windows. Consider including lldir.h instead. -#endif // !LL_WINDOWS - -#ifndef LL_LLDIR_WIN32_H -#define LL_LLDIR_WIN32_H - -#include "lldir.h" - -class LLDir_Win32 : public LLDir -{ -public: - LLDir_Win32(); - virtual ~LLDir_Win32(); - - /*virtual*/ void initAppDirs(const std::string &app_name, - const std::string& app_read_only_data_dir); - - /*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); - -private: - void* mDirSearch_h; - llutf16string mCurrentDir; -}; - -#endif // LL_LLDIR_WIN32_H - - diff --git a/indra/llcache/lldirguard.h b/indra/llcache/lldirguard.h deleted file mode 100644 index 37b9e9b83e..0000000000 --- a/indra/llcache/lldirguard.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file lldirguard.h - * @brief Protect working directory from being changed in scope. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_DIRGUARD_H -#define LL_DIRGUARD_H - -#include "linden_common.h" -#include "llerror.h" - -#if LL_WINDOWS -class LLDirectoryGuard -{ -public: - LLDirectoryGuard() - { - mOrigDirLen = GetCurrentDirectory(MAX_PATH, mOrigDir); - } - - ~LLDirectoryGuard() - { - mFinalDirLen = GetCurrentDirectory(MAX_PATH, mFinalDir); - if ((mOrigDirLen!=mFinalDirLen) || - (wcsncmp(mOrigDir,mFinalDir,mOrigDirLen)!=0)) - { - // Dir has changed - std::string mOrigDirUtf8 = utf16str_to_utf8str(llutf16string(mOrigDir)); - std::string mFinalDirUtf8 = utf16str_to_utf8str(llutf16string(mFinalDir)); - LL_INFOS() << "Resetting working dir from " << mFinalDirUtf8 << " to " << mOrigDirUtf8 << LL_ENDL; - SetCurrentDirectory(mOrigDir); - } - } - -private: - TCHAR mOrigDir[MAX_PATH]; - DWORD mOrigDirLen; - TCHAR mFinalDir[MAX_PATH]; - DWORD mFinalDirLen; -}; -#else // No-op outside Windows. -class LLDirectoryGuard -{ -public: - LLDirectoryGuard() {} - ~LLDirectoryGuard() {} -}; -#endif - - -#endif diff --git a/indra/llcache/lldiriterator.cpp b/indra/llcache/lldiriterator.cpp deleted file mode 100644 index 3eb64e69d9..0000000000 --- a/indra/llcache/lldiriterator.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/** - * @file lldiriterator.cpp - * @brief Iterator through directory entries matching the search pattern. - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "lldiriterator.h" - -#include "fix_macros.h" -#include -#include - -namespace fs = boost::filesystem; - -static std::string glob_to_regex(const std::string& glob); - -class LLDirIterator::Impl -{ -public: - Impl(const std::string &dirname, const std::string &mask); - ~Impl(); - - bool next(std::string &fname); - -private: - boost::regex mFilterExp; - fs::directory_iterator mIter; - bool mIsValid; -}; - -LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) - : mIsValid(false) -{ -#ifdef LL_WINDOWS // or BOOST_WINDOWS_API - fs::path dir_path(utf8str_to_utf16str(dirname)); -#else - fs::path dir_path(dirname); -#endif - - bool is_dir = false; - - // Check if path is a directory. - try - { - is_dir = fs::is_directory(dir_path); - } - catch (const fs::filesystem_error& e) - { - LL_WARNS() << e.what() << LL_ENDL; - return; - } - - if (!is_dir) - { - LL_WARNS() << "Invalid path: \"" << dir_path.string() << "\"" << LL_ENDL; - return; - } - - // Initialize the directory iterator for the given path. - try - { - mIter = fs::directory_iterator(dir_path); - } - catch (const fs::filesystem_error& e) - { - LL_WARNS() << e.what() << LL_ENDL; - return; - } - - // Convert the glob mask to a regular expression - std::string exp = glob_to_regex(mask); - - // Initialize boost::regex with the expression converted from - // the glob mask. - // An exception is thrown if the expression is not valid. - try - { - mFilterExp.assign(exp); - } - catch (boost::regex_error& e) - { - LL_WARNS() << "\"" << exp << "\" is not a valid regular expression: " - << e.what() << LL_ENDL; - return; - } - - mIsValid = true; -} - -LLDirIterator::Impl::~Impl() -{ -} - -bool LLDirIterator::Impl::next(std::string &fname) -{ - fname = ""; - - if (!mIsValid) - { - LL_WARNS() << "The iterator is not correctly initialized." << LL_ENDL; - return false; - } - - fs::directory_iterator end_itr; // default construction yields past-the-end - bool found = false; - - // Check if path is a directory. - try - { - while (mIter != end_itr && !found) - { - boost::smatch match; - std::string name = mIter->path().filename().string(); - found = boost::regex_match(name, match, mFilterExp); - if (found) - { - fname = name; - } - - ++mIter; - } - } - catch (const fs::filesystem_error& e) - { - LL_WARNS() << e.what() << LL_ENDL; - } - - return found; -} - -/** -Converts the incoming glob into a regex. This involves -converting incoming glob expressions to regex equivilents and -at the same time, escaping any regex meaningful characters which -do not have glob meaning, i.e. - .()+|^$ -in the input. -*/ -std::string glob_to_regex(const std::string& glob) -{ - std::string regex; - regex.reserve(glob.size()<<1); - S32 braces = 0; - bool escaped = false; - bool square_brace_open = false; - - for (std::string::const_iterator i = glob.begin(); i != glob.end(); ++i) - { - char c = *i; - - switch (c) - { - case '*': - if (glob.begin() == i) - { - regex+="[^.].*"; - } - else - { - regex+= escaped ? "*" : ".*"; - } - break; - case '?': - regex+= escaped ? '?' : '.'; - break; - case '{': - braces++; - regex+='('; - break; - case '}': - if (!braces) - { - LL_ERRS() << "glob_to_regex: Closing brace without an equivalent opening brace: " << glob << LL_ENDL; - } - - regex+=')'; - braces--; - break; - case ',': - regex+= braces ? '|' : c; - break; - case '!': - regex+= square_brace_open ? '^' : c; - break; - case '.': // This collection have different regex meaning - case '^': // and so need escaping. - case '(': - case ')': - case '+': - case '|': - case '$': - regex += '\\'; - default: - regex += c; - break; - } - - escaped = ('\\' == c); - square_brace_open = ('[' == c); - } - - if (braces) - { - LL_ERRS() << "glob_to_regex: Unterminated brace expression: " << glob << LL_ENDL; - } - - return regex; -} - -LLDirIterator::LLDirIterator(const std::string &dirname, const std::string &mask) -{ - mImpl = new Impl(dirname, mask); -} - -LLDirIterator::~LLDirIterator() -{ - delete mImpl; -} - -bool LLDirIterator::next(std::string &fname) -{ - return mImpl->next(fname); -} diff --git a/indra/llcache/lldiriterator.h b/indra/llcache/lldiriterator.h deleted file mode 100644 index 0b48be41b3..0000000000 --- a/indra/llcache/lldiriterator.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file lldiriterator.h - * @brief Iterator through directory entries matching the search pattern. - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLDIRITERATOR_H -#define LL_LLDIRITERATOR_H - -#include "linden_common.h" - -/** - * Class LLDirIterator - * - * Iterates through directory entries matching the search pattern. - */ -class LLDirIterator -{ -public: - /** - * Constructs LLDirIterator object to search for glob pattern - * matches in a directory. - * - * @param dirname - name of a directory to search in. - * @param mask - search pattern, a glob expression - * - * Wildcards supported in glob expressions: - * -------------------------------------------------------------- - * | Wildcard | Matches | - * -------------------------------------------------------------- - * | * |zero or more characters | - * | ? |exactly one character | - * | [abcde] |exactly one character listed | - * | [a-e] |exactly one character in the given range | - * | [!abcde] |any character that is not listed | - * | [!a-e] |any character that is not in the given range | - * | {abc,xyz} |exactly one entire word in the options given | - * -------------------------------------------------------------- - */ - LLDirIterator(const std::string &dirname, const std::string &mask); - - ~LLDirIterator(); - - /** - * Searches for the next directory entry matching the glob mask - * specified upon iterator construction. - * Returns true if a match is found, sets fname - * parameter to the name of the matched directory entry and - * increments the iterator position. - * - * Typical usage: - * - * LLDirIterator iter(directory, pattern); - * if ( iter.next(scanResult) ) - * - * - * @param fname - name of the matched directory entry. - * @return true if a match is found, false otherwise. - */ - bool next(std::string &fname); - -protected: - class Impl; - Impl* mImpl; -}; - -#endif //LL_LLDIRITERATOR_H diff --git a/indra/llcache/lldiskcache.cpp b/indra/llcache/lldiskcache.cpp deleted file mode 100644 index af93049e07..0000000000 --- a/indra/llcache/lldiskcache.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/** - * @file lldiskcache.cpp - * @brief Implementation of virtual file - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "lldiskcache.h" - -#include "llerror.h" -#include "llthread.h" -#include "lltimer.h" -#include "llfasttimer.h" -#include "llmemory.h" - -#include -#include "lldir.h" - -const S32 LLDiskCache::READ = 0x00000001; -const S32 LLDiskCache::WRITE = 0x00000002; -const S32 LLDiskCache::READ_WRITE = 0x00000003; // LLDiskCache::READ & LLDiskCache::WRITE -const S32 LLDiskCache::APPEND = 0x00000006; // 0x00000004 & LLDiskCache::WRITE - -static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait"); - -LLDiskCache::LLDiskCache(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode) -{ - mFileType = file_type; - mFileID = file_id; - mPosition = 0; - mBytesRead = 0; - mReadComplete = FALSE; - mMode = mode; -} - -LLDiskCache::~LLDiskCache() -{ -} - -const std::string assetTypeToString(LLAssetType::EType at) -{ - /** - * Make use of the C++17 (or is it 14) feature that allows - * for inline initialization of an std::map<> - */ - typedef std::map asset_type_to_name_t; - asset_type_to_name_t asset_type_to_name = - { - { LLAssetType::AT_TEXTURE, "TEXTURE" }, - { LLAssetType::AT_SOUND, "SOUND" }, - { LLAssetType::AT_CALLINGCARD, "CALLINGCARD" }, - { LLAssetType::AT_LANDMARK, "LANDMARK" }, - { LLAssetType::AT_SCRIPT, "SCRIPT" }, - { LLAssetType::AT_CLOTHING, "CLOTHING" }, - { LLAssetType::AT_OBJECT, "OBJECT" }, - { LLAssetType::AT_NOTECARD, "NOTECARD" }, - { LLAssetType::AT_CATEGORY, "CATEGORY" }, - { LLAssetType::AT_LSL_TEXT, "LSL_TEXT" }, - { LLAssetType::AT_LSL_BYTECODE, "LSL_BYTECODE" }, - { LLAssetType::AT_TEXTURE_TGA, "TEXTURE_TGA" }, - { LLAssetType::AT_BODYPART, "BODYPART" }, - { LLAssetType::AT_SOUND_WAV, "SOUND_WAV" }, - { LLAssetType::AT_IMAGE_TGA, "IMAGE_TGA" }, - { LLAssetType::AT_IMAGE_JPEG, "IMAGE_JPEG" }, - { LLAssetType::AT_ANIMATION, "ANIMATION" }, - { LLAssetType::AT_GESTURE, "GESTURE" }, - { LLAssetType::AT_SIMSTATE, "SIMSTATE" }, - { LLAssetType::AT_LINK, "LINK" }, - { LLAssetType::AT_LINK_FOLDER, "LINK_FOLDER" }, - { LLAssetType::AT_MARKETPLACE_FOLDER, "MARKETPLACE_FOLDER" }, - { LLAssetType::AT_WIDGET, "WIDGET" }, - { LLAssetType::AT_PERSON, "PERSON" }, - { LLAssetType::AT_MESH, "MESH" }, - { LLAssetType::AT_SETTINGS, "SETTINGS" }, - { LLAssetType::AT_UNKNOWN, "UNKNOWN" } - }; - - asset_type_to_name_t::iterator iter = asset_type_to_name.find(at); - if (iter != asset_type_to_name.end()) - { - return iter->second; - } - - return std::string("UNKNOWN"); -} - -const std::string idToFilepath(const std::string id, LLAssetType::EType at) -{ - /** - * For the moment this is just {UUID}_{ASSET_TYPE}.txt but of - * course, will be greatly expanded upon - */ - std::ostringstream ss; - ss << "00cache_"; - ss << id; - ss << "_"; - ss << assetTypeToString(at); - ss << ".txt"; - - const std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ss.str()); - - return filepath; -} - -// static -bool LLDiskCache::getExists(const LLUUID &file_id, const LLAssetType::EType file_type) -{ - std::string id_str; - file_id.toString(id_str); - const std::string filename = idToFilepath(id_str, file_type); - - std::ifstream file(filename, std::ios::binary); - if (file.is_open()) - { - file.seekg(0, std::ios::end); - return file.tellg() > 0; - } - return false; -} - -// static -bool LLDiskCache::removeFile(const LLUUID &file_id, const LLAssetType::EType file_type) -{ - std::string id_str; - file_id.toString(id_str); - const std::string filename = idToFilepath(id_str, file_type); - - std::remove(filename.c_str()); - - return true; -} - -// static -bool LLDiskCache::renameFile(const LLUUID &old_file_id, const LLAssetType::EType old_file_type, - const LLUUID &new_file_id, const LLAssetType::EType new_file_type) -{ - std::string old_id_str; - old_file_id.toString(old_id_str); - const std::string old_filename = idToFilepath(old_id_str, old_file_type); - - std::string new_id_str; - new_file_id.toString(new_id_str); - const std::string new_filename = idToFilepath(new_id_str, new_file_type); - - if (std::rename(old_filename.c_str(), new_filename.c_str())) - { - // We would like to return FALSE here indicating the operation - // failed but the original code does not and doing so seems to - // break a lot of things so we go with the flow... - //return FALSE; - } - - return TRUE; -} - -// static -S32 LLDiskCache::getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type) -{ - std::string id_str; - file_id.toString(id_str); - const std::string filename = idToFilepath(id_str, file_type); - - S32 file_size = 0; - std::ifstream file(filename, std::ios::binary); - if (file.is_open()) - { - file.seekg(0, std::ios::end); - file_size = file.tellg(); - } - - return file_size; -} - -BOOL LLDiskCache::read(U8 *buffer, S32 bytes, BOOL async, F32 priority) -{ - BOOL success = TRUE; - - mReadComplete = FALSE; - - std::string id; - mFileID.toString(id); - const std::string filename = idToFilepath(id, mFileType); - - std::ifstream file(filename, std::ios::binary); - if (file.is_open()) - { - file.seekg(mPosition, std::ios::beg); - - file.read((char*)buffer, bytes); - - if (file) - { - mBytesRead = bytes; - } - else - { - mBytesRead = file.gcount(); - } - - file.close(); - - mPosition += mBytesRead; - if (!mBytesRead) - { - success = FALSE; - } - - mReadComplete = TRUE; - } - - return success; -} - -BOOL LLDiskCache::isReadComplete() -{ - if (mReadComplete) - { - return TRUE; - } - - return FALSE; -} - -S32 LLDiskCache::getLastBytesRead() -{ - return mBytesRead; -} - -BOOL LLDiskCache::eof() -{ - return mPosition >= getSize(); -} - -BOOL LLDiskCache::write(const U8 *buffer, S32 bytes) -{ - std::string id_str; - mFileID.toString(id_str); - const std::string filename = idToFilepath(id_str, mFileType); - - BOOL success = FALSE; - - if (mMode == APPEND) - { - std::ofstream ofs(filename, std::ios::app | std::ios::binary); - if (ofs) - { - ofs.write((const char*)buffer, bytes); - - success = TRUE; - } - } - else - { - std::ofstream ofs(filename, std::ios::binary); - if (ofs) - { - ofs.write((const char*)buffer, bytes); - - mPosition += bytes; - - success = TRUE; - } - } - - return success; -} - -//static -BOOL LLDiskCache::writeFile(const U8 *buffer, S32 bytes, const LLUUID &uuid, LLAssetType::EType type) -{ - LLDiskCache file(uuid, type, LLDiskCache::WRITE); - file.setMaxSize(bytes); - return file.write(buffer, bytes); -} - -BOOL LLDiskCache::seek(S32 offset, S32 origin) -{ - if (-1 == origin) - { - origin = mPosition; - } - - S32 new_pos = origin + offset; - - S32 size = getSize(); - - if (new_pos > size) - { - LL_WARNS() << "Attempt to seek past end of file" << LL_ENDL; - - mPosition = size; - return FALSE; - } - else if (new_pos < 0) - { - LL_WARNS() << "Attempt to seek past beginning of file" << LL_ENDL; - - mPosition = 0; - return FALSE; - } - - mPosition = new_pos; - return TRUE; -} - -S32 LLDiskCache::tell() const -{ - return mPosition; -} - -S32 LLDiskCache::getSize() -{ - return LLDiskCache::getFileSize(mFileID, mFileType); -} - -S32 LLDiskCache::getMaxSize() -{ - // offer up a huge size since we don't care what the max is - return INT_MAX; -} - -BOOL LLDiskCache::setMaxSize(S32 size) -{ - // we don't care what the max size is so we do nothing - // and return true to indicate all was okay - return TRUE; -} - -BOOL LLDiskCache::rename(const LLUUID &new_id, const LLAssetType::EType new_type) -{ - LLDiskCache::renameFile(mFileID, mFileType, new_id, new_type); - - mFileID = new_id; - mFileType = new_type; - - return TRUE; -} - -BOOL LLDiskCache::remove() -{ - LLDiskCache::removeFile(mFileID, mFileType); - - return TRUE; -} - -// static -void LLDiskCache::initClass() -{ -} - -// static -void LLDiskCache::cleanupClass() -{ -} - -bool LLDiskCache::isLocked() -{ - // I don't think we care about this test since there is no locking - // TODO: remove this function and calling sites? - return FALSE; -} - -void LLDiskCache::waitForLock() -{ - // TODO: remove this function and calling sites? -} diff --git a/indra/llcache/lldiskcache.h b/indra/llcache/lldiskcache.h deleted file mode 100644 index 7ad06a8689..0000000000 --- a/indra/llcache/lldiskcache.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file lldiskcacke.h - * @brief Definition of virtual file - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLDISKCACHE_H -#define LL_LLDISKCACHE_H - -#include "lluuid.h" -#include "llassettype.h" - -class LLDiskCache -{ -public: - LLDiskCache(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode = LLDiskCache::READ); - ~LLDiskCache(); - - BOOL read(U8 *buffer, S32 bytes, BOOL async = FALSE, F32 priority = 128.f); /* Flawfinder: ignore */ - BOOL isReadComplete(); - S32 getLastBytesRead(); - BOOL eof(); - - BOOL write(const U8 *buffer, S32 bytes); - static BOOL writeFile(const U8 *buffer, S32 bytes, const LLUUID &uuid, LLAssetType::EType type); - BOOL seek(S32 offset, S32 origin = -1); - S32 tell() const; - - S32 getSize(); - S32 getMaxSize(); - BOOL setMaxSize(S32 size); - BOOL rename(const LLUUID &new_id, const LLAssetType::EType new_type); - BOOL remove(); - - bool isLocked(); - void waitForLock(); - - static bool getExists(const LLUUID &file_id, const LLAssetType::EType file_type); - static bool removeFile(const LLUUID &file_id, const LLAssetType::EType file_type); - 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 S32 getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type); - - static void initClass(); - static void cleanupClass(); - -public: - static const S32 READ; - static const S32 WRITE; - static const S32 READ_WRITE; - static const S32 APPEND; - -protected: - LLAssetType::EType mFileType; - BOOL mReadComplete; - LLUUID mFileID; - S32 mPosition; - S32 mMode; - S32 mBytesRead; -}; - -#endif // LL_LLDISKCACHE_H diff --git a/indra/llcache/lllfsthread.cpp b/indra/llcache/lllfsthread.cpp deleted file mode 100644 index be8e83a56f..0000000000 --- a/indra/llcache/lllfsthread.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/** - * @file lllfsthread.cpp - * @brief LLLFSThread base class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "lllfsthread.h" -#include "llstl.h" -#include "llapr.h" - -//============================================================================ - -/*static*/ LLLFSThread* LLLFSThread::sLocal = NULL; - -//============================================================================ -// Run on MAIN thread -//static -void LLLFSThread::initClass(bool local_is_threaded) -{ - llassert(sLocal == NULL); - sLocal = new LLLFSThread(local_is_threaded); -} - -//static -S32 LLLFSThread::updateClass(U32 ms_elapsed) -{ - sLocal->update((F32)ms_elapsed); - return sLocal->getPending(); -} - -//static -void LLLFSThread::cleanupClass() -{ - llassert(sLocal != NULL); - sLocal->setQuitting(); - while (sLocal->getPending()) - { - sLocal->update(0); - } - delete sLocal; - sLocal = NULL; -} - -//---------------------------------------------------------------------------- - -LLLFSThread::LLLFSThread(bool threaded) : - LLQueuedThread("LFS", threaded), - mPriorityCounter(PRIORITY_LOWBITS) -{ - if(!mLocalAPRFilePoolp) - { - mLocalAPRFilePoolp = new LLVolatileAPRPool() ; - } -} - -LLLFSThread::~LLLFSThread() -{ - // mLocalAPRFilePoolp cleanup in LLThread - // ~LLQueuedThread() will be called here -} - -//---------------------------------------------------------------------------- - -LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfinder: ignore */ - U8* buffer, S32 offset, S32 numbytes, - Responder* responder, U32 priority) -{ - handle_t handle = generateHandle(); - - if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter(); - else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW; // All reads are at least PRIORITY_LOW - - Request* req = new Request(this, handle, priority, - FILE_READ, filename, - buffer, offset, numbytes, - responder); - - bool res = addRequest(req); - if (!res) - { - LL_ERRS() << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << LL_ENDL; - } - - return handle; -} - -LLLFSThread::handle_t LLLFSThread::write(const std::string& filename, - U8* buffer, S32 offset, S32 numbytes, - Responder* responder, U32 priority) -{ - handle_t handle = generateHandle(); - - if (priority == 0) priority = PRIORITY_LOW | priorityCounter(); - - Request* req = new Request(this, handle, priority, - FILE_WRITE, filename, - buffer, offset, numbytes, - responder); - - bool res = addRequest(req); - if (!res) - { - LL_ERRS() << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << LL_ENDL; - } - - return handle; -} - -//============================================================================ - -LLLFSThread::Request::Request(LLLFSThread* thread, - handle_t handle, U32 priority, - operation_t op, const std::string& filename, - U8* buffer, S32 offset, S32 numbytes, - Responder* responder) : - QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE), - mThread(thread), - mOperation(op), - mFileName(filename), - mBuffer(buffer), - mOffset(offset), - mBytes(numbytes), - mBytesRead(0), - mResponder(responder) -{ - if (numbytes <= 0) - { - LL_WARNS() << "LLLFSThread: Request with numbytes = " << numbytes << LL_ENDL; - } -} - -LLLFSThread::Request::~Request() -{ -} - -// virtual, called from own thread -void LLLFSThread::Request::finishRequest(bool completed) -{ - if (mResponder.notNull()) - { - mResponder->completed(completed ? mBytesRead : 0); - mResponder = NULL; - } -} - -void LLLFSThread::Request::deleteRequest() -{ - if (getStatus() == STATUS_QUEUED) - { - LL_ERRS() << "Attempt to delete a queued LLLFSThread::Request!" << LL_ENDL; - } - if (mResponder.notNull()) - { - mResponder->completed(0); - mResponder = NULL; - } - LLQueuedThread::QueuedRequest::deleteRequest(); -} - -bool LLLFSThread::Request::processRequest() -{ - bool complete = false; - if (mOperation == FILE_READ) - { - llassert(mOffset >= 0); - LLAPRFile infile ; // auto-closes - infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool()); - if (!infile.getFileHandle()) - { - LL_WARNS() << "LLLFS: Unable to read file: " << mFileName << LL_ENDL; - mBytesRead = 0; // fail - return true; - } - S32 off; - if (mOffset < 0) - off = infile.seek(APR_END, 0); - else - off = infile.seek(APR_SET, mOffset); - llassert_always(off >= 0); - mBytesRead = infile.read(mBuffer, mBytes ); - complete = true; -// LL_INFOS() << "LLLFSThread::READ:" << mFileName << " Bytes: " << mBytesRead << LL_ENDL; - } - else if (mOperation == FILE_WRITE) - { - apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; - if (mOffset < 0) - flags |= APR_APPEND; - LLAPRFile outfile ; // auto-closes - outfile.open(mFileName, flags, mThread->getLocalAPRFilePool()); - if (!outfile.getFileHandle()) - { - LL_WARNS() << "LLLFS: Unable to write file: " << mFileName << LL_ENDL; - mBytesRead = 0; // fail - return true; - } - if (mOffset >= 0) - { - S32 seek = outfile.seek(APR_SET, mOffset); - if (seek < 0) - { - LL_WARNS() << "LLLFS: Unable to write file (seek failed): " << mFileName << LL_ENDL; - mBytesRead = 0; // fail - return true; - } - } - mBytesRead = outfile.write(mBuffer, mBytes ); - complete = true; -// LL_INFOS() << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << LL_ENDL; - } - else - { - LL_ERRS() << "LLLFSThread::unknown operation: " << (S32)mOperation << LL_ENDL; - } - return complete; -} - -//============================================================================ - -LLLFSThread::Responder::~Responder() -{ -} - -//============================================================================ diff --git a/indra/llcache/lllfsthread.h b/indra/llcache/lllfsthread.h deleted file mode 100644 index 58f658f7ba..0000000000 --- a/indra/llcache/lllfsthread.h +++ /dev/null @@ -1,147 +0,0 @@ -/** - * @file lllfsthread.h - * @brief LLLFSThread base class - * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLLFSTHREAD_H -#define LL_LLLFSTHREAD_H - -#include -#include -#include -#include - -#include "llpointer.h" -#include "llqueuedthread.h" - -//============================================================================ -// Threaded Local File System -//============================================================================ - -class LLLFSThread : public LLQueuedThread -{ - //------------------------------------------------------------------------ -public: - enum operation_t { - FILE_READ, - FILE_WRITE, - FILE_RENAME, - FILE_REMOVE - }; - - //------------------------------------------------------------------------ -public: - - class Responder : public LLThreadSafeRefCount - { - protected: - ~Responder(); - public: - virtual void completed(S32 bytes) = 0; - }; - - class Request : public QueuedRequest - { - protected: - virtual ~Request(); // use deleteRequest() - - public: - Request(LLLFSThread* thread, - handle_t handle, U32 priority, - operation_t op, const std::string& filename, - U8* buffer, S32 offset, S32 numbytes, - Responder* responder); - - S32 getBytes() - { - return mBytes; - } - S32 getBytesRead() - { - return mBytesRead; - } - S32 getOperation() - { - return mOperation; - } - U8* getBuffer() - { - return mBuffer; - } - const std::string& getFilename() - { - return mFileName; - } - - /*virtual*/ bool processRequest(); - /*virtual*/ void finishRequest(bool completed); - /*virtual*/ void deleteRequest(); - - private: - LLLFSThread* mThread; - operation_t mOperation; - - std::string mFileName; - - U8* mBuffer; // dest for reads, source for writes, new UUID for rename - S32 mOffset; // offset into file, -1 = append (WRITE only) - S32 mBytes; // bytes to read from file, -1 = all - S32 mBytesRead; // bytes read from file - - LLPointer mResponder; - }; - - //------------------------------------------------------------------------ -public: - LLLFSThread(bool threaded = TRUE); - ~LLLFSThread(); - - // Return a Request handle - handle_t read(const std::string& filename, /* Flawfinder: ignore */ - U8* buffer, S32 offset, S32 numbytes, - Responder* responder, U32 pri=0); - handle_t write(const std::string& filename, - U8* buffer, S32 offset, S32 numbytes, - Responder* responder, U32 pri=0); - - // Misc - U32 priorityCounter() { return mPriorityCounter-- & PRIORITY_LOWBITS; } // Use to order IO operations - - // static initializers - static void initClass(bool local_is_threaded = TRUE); // Setup sLocal - static S32 updateClass(U32 ms_elapsed); - static void cleanupClass(); // Delete sLocal - - -private: - U32 mPriorityCounter; - -public: - static LLLFSThread* sLocal; // Default local file thread -}; - -//============================================================================ - - -#endif // LL_LLLFSTHREAD_H diff --git a/indra/llcache/tests/lldir_test.cpp b/indra/llcache/tests/lldir_test.cpp deleted file mode 100644 index 3cff622a4b..0000000000 --- a/indra/llcache/tests/lldir_test.cpp +++ /dev/null @@ -1,767 +0,0 @@ -/** - * @file lldir_test.cpp - * @date 2008-05 - * @brief LLDir test cases. - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llstring.h" -#include "tests/StringVec.h" -#include "../lldir.h" -#include "../lldiriterator.h" - -#include "../test/lltut.h" -#include "stringize.h" -#include -#include - -using boost::assign::list_of; - -// We use ensure_equals(..., vec(list_of(...))) not because it's functionally -// required, but because ensure_equals() knows how to format a StringVec. -// Turns out that when ensure_equals() displays a test failure with just -// list_of("string")("another"), you see 'stringanother' vs. '("string", -// "another")'. -StringVec vec(const StringVec& v) -{ - return v; -} - -// For some tests, use a dummy LLDir that uses memory data instead of touching -// the filesystem -struct LLDir_Dummy: public LLDir -{ - /*----------------------------- LLDir API ------------------------------*/ - LLDir_Dummy() - { - // Initialize important LLDir data members based on the filesystem - // data below. - mDirDelimiter = "/"; - mExecutableDir = "install"; - mExecutableFilename = "test"; - mExecutablePathAndName = add(mExecutableDir, mExecutableFilename); - mWorkingDir = mExecutableDir; - mAppRODataDir = "install"; - mSkinBaseDir = add(mAppRODataDir, "skins"); - mOSUserDir = "user"; - mOSUserAppDir = mOSUserDir; - mLindenUserDir = ""; - - // Make the dummy filesystem look more or less like what we expect in - // the real one. - static const char* preload[] = - { - // We group these fixture-data pathnames by basename, rather than - // sorting by full path as you might expect, because the outcome - // of each test strongly depends on which skins/languages provide - // a given basename. - "install/skins/default/colors.xml", - "install/skins/steam/colors.xml", - "user/skins/default/colors.xml", - "user/skins/steam/colors.xml", - - "install/skins/default/xui/en/strings.xml", - "install/skins/default/xui/fr/strings.xml", - "install/skins/steam/xui/en/strings.xml", - "install/skins/steam/xui/fr/strings.xml", - "user/skins/default/xui/en/strings.xml", - "user/skins/default/xui/fr/strings.xml", - "user/skins/steam/xui/en/strings.xml", - "user/skins/steam/xui/fr/strings.xml", - - "install/skins/default/xui/en/floater.xml", - "install/skins/default/xui/fr/floater.xml", - "user/skins/default/xui/fr/floater.xml", - - "install/skins/default/xui/en/newfile.xml", - "install/skins/default/xui/fr/newfile.xml", - "user/skins/default/xui/en/newfile.xml", - - "install/skins/default/html/en-us/welcome.html", - "install/skins/default/html/fr/welcome.html", - - "install/skins/default/textures/only_default.jpeg", - "install/skins/steam/textures/only_steam.jpeg", - "user/skins/default/textures/only_user_default.jpeg", - "user/skins/steam/textures/only_user_steam.jpeg", - - "install/skins/default/future/somefile.txt" - }; - BOOST_FOREACH(const char* path, preload) - { - buildFilesystem(path); - } - } - - virtual ~LLDir_Dummy() {} - - virtual void initAppDirs(const std::string& app_name, const std::string& app_read_only_data_dir) - { - // Implement this when we write a test that needs it - } - - virtual std::string getCurPath() - { - // Implement this when we write a test that needs it - return ""; - } - - virtual U32 countFilesInDir(const std::string& dirname, const std::string& mask) - { - // Implement this when we write a test that needs it - return 0; - } - - virtual bool fileExists(const std::string& pathname) const - { - // Record fileExists() calls so we can check whether caching is - // working right. Certain LLDir calls should be able to make decisions - // without calling fileExists() again, having already checked existence. - mChecked.insert(pathname); - // For our simple flat set of strings, see whether the identical - // pathname exists in our set. - return (mFilesystem.find(pathname) != mFilesystem.end()); - } - - virtual std::string getLLPluginLauncher() - { - // Implement this when we write a test that needs it - return ""; - } - - virtual std::string getLLPluginFilename(std::string base_name) - { - // Implement this when we write a test that needs it - return ""; - } - - /*----------------------------- Dummy data -----------------------------*/ - void clearFilesystem() { mFilesystem.clear(); } - void buildFilesystem(const std::string& path) - { - // Split the pathname on slashes, ignoring leading, trailing, doubles - StringVec components; - LLStringUtil::getTokens(path, components, "/"); - // Ensure we have an entry representing every level of this path - std::string partial; - BOOST_FOREACH(std::string component, components) - { - append(partial, component); - mFilesystem.insert(partial); - } - } - - void clear_checked() { mChecked.clear(); } - void ensure_checked(const std::string& pathname) const - { - tut::ensure(STRINGIZE(pathname << " was not checked but should have been"), - mChecked.find(pathname) != mChecked.end()); - } - void ensure_not_checked(const std::string& pathname) const - { - tut::ensure(STRINGIZE(pathname << " was checked but should not have been"), - mChecked.find(pathname) == mChecked.end()); - } - - std::set mFilesystem; - mutable std::set mChecked; -}; - -namespace tut -{ - struct LLDirTest - { - }; - typedef test_group LLDirTest_t; - typedef LLDirTest_t::object LLDirTest_object_t; - tut::LLDirTest_t tut_LLDirTest("LLDir"); - - template<> template<> - void LLDirTest_object_t::test<1>() - // getDirDelimiter - { - ensure("getDirDelimiter", !gDirUtilp->getDirDelimiter().empty()); - } - - template<> template<> - void LLDirTest_object_t::test<2>() - // getBaseFileName - { - std::string delim = gDirUtilp->getDirDelimiter(); - std::string rawFile = "foo"; - std::string rawFileExt = "foo.bAr"; - std::string rawFileNullExt = "foo."; - std::string rawExt = ".bAr"; - std::string rawDot = "."; - std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; - std::string pathExt = pathNoExt + ".eXt"; - std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; - std::string dottedPathExt = dottedPathNoExt + ".eXt"; - - // foo[.bAr] - - ensure_equals("getBaseFileName/r-no-ext/no-strip-exten", - gDirUtilp->getBaseFileName(rawFile, false), - "foo"); - - ensure_equals("getBaseFileName/r-no-ext/strip-exten", - gDirUtilp->getBaseFileName(rawFile, true), - "foo"); - - ensure_equals("getBaseFileName/r-ext/no-strip-exten", - gDirUtilp->getBaseFileName(rawFileExt, false), - "foo.bAr"); - - ensure_equals("getBaseFileName/r-ext/strip-exten", - gDirUtilp->getBaseFileName(rawFileExt, true), - "foo"); - - // foo. - - ensure_equals("getBaseFileName/rn-no-ext/no-strip-exten", - gDirUtilp->getBaseFileName(rawFileNullExt, false), - "foo."); - - ensure_equals("getBaseFileName/rn-no-ext/strip-exten", - gDirUtilp->getBaseFileName(rawFileNullExt, true), - "foo"); - - // .bAr - // interesting case - with no basename, this IS the basename, not the extension. - - ensure_equals("getBaseFileName/e-ext/no-strip-exten", - gDirUtilp->getBaseFileName(rawExt, false), - ".bAr"); - - ensure_equals("getBaseFileName/e-ext/strip-exten", - gDirUtilp->getBaseFileName(rawExt, true), - ".bAr"); - - // . - - ensure_equals("getBaseFileName/d/no-strip-exten", - gDirUtilp->getBaseFileName(rawDot, false), - "."); - - ensure_equals("getBaseFileName/d/strip-exten", - gDirUtilp->getBaseFileName(rawDot, true), - "."); - - // aa/bb/cc/dd/ee[.eXt] - - ensure_equals("getBaseFileName/no-ext/no-strip-exten", - gDirUtilp->getBaseFileName(pathNoExt, false), - "ee"); - - ensure_equals("getBaseFileName/no-ext/strip-exten", - gDirUtilp->getBaseFileName(pathNoExt, true), - "ee"); - - ensure_equals("getBaseFileName/ext/no-strip-exten", - gDirUtilp->getBaseFileName(pathExt, false), - "ee.eXt"); - - ensure_equals("getBaseFileName/ext/strip-exten", - gDirUtilp->getBaseFileName(pathExt, true), - "ee"); - - // aa/bb/cc.dd/ee[.eXt] - - ensure_equals("getBaseFileName/d-no-ext/no-strip-exten", - gDirUtilp->getBaseFileName(dottedPathNoExt, false), - "ee"); - - ensure_equals("getBaseFileName/d-no-ext/strip-exten", - gDirUtilp->getBaseFileName(dottedPathNoExt, true), - "ee"); - - ensure_equals("getBaseFileName/d-ext/no-strip-exten", - gDirUtilp->getBaseFileName(dottedPathExt, false), - "ee.eXt"); - - ensure_equals("getBaseFileName/d-ext/strip-exten", - gDirUtilp->getBaseFileName(dottedPathExt, true), - "ee"); - } - - template<> template<> - void LLDirTest_object_t::test<3>() - // getDirName - { - std::string delim = gDirUtilp->getDirDelimiter(); - std::string rawFile = "foo"; - std::string rawFileExt = "foo.bAr"; - std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; - std::string pathExt = pathNoExt + ".eXt"; - std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; - std::string dottedPathExt = dottedPathNoExt + ".eXt"; - - // foo[.bAr] - - ensure_equals("getDirName/r-no-ext", - gDirUtilp->getDirName(rawFile), - ""); - - ensure_equals("getDirName/r-ext", - gDirUtilp->getDirName(rawFileExt), - ""); - - // aa/bb/cc/dd/ee[.eXt] - - ensure_equals("getDirName/no-ext", - gDirUtilp->getDirName(pathNoExt), - "aa" + delim + "bb" + delim + "cc" + delim + "dd"); - - ensure_equals("getDirName/ext", - gDirUtilp->getDirName(pathExt), - "aa" + delim + "bb" + delim + "cc" + delim + "dd"); - - // aa/bb/cc.dd/ee[.eXt] - - ensure_equals("getDirName/d-no-ext", - gDirUtilp->getDirName(dottedPathNoExt), - "aa" + delim + "bb" + delim + "cc.dd"); - - ensure_equals("getDirName/d-ext", - gDirUtilp->getDirName(dottedPathExt), - "aa" + delim + "bb" + delim + "cc.dd"); - } - - template<> template<> - void LLDirTest_object_t::test<4>() - // getExtension - { - std::string delim = gDirUtilp->getDirDelimiter(); - std::string rawFile = "foo"; - std::string rawFileExt = "foo.bAr"; - std::string rawFileNullExt = "foo."; - std::string rawExt = ".bAr"; - std::string rawDot = "."; - std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; - std::string pathExt = pathNoExt + ".eXt"; - std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; - std::string dottedPathExt = dottedPathNoExt + ".eXt"; - - // foo[.bAr] - - ensure_equals("getExtension/r-no-ext", - gDirUtilp->getExtension(rawFile), - ""); - - ensure_equals("getExtension/r-ext", - gDirUtilp->getExtension(rawFileExt), - "bar"); - - // foo. - - ensure_equals("getExtension/rn-no-ext", - gDirUtilp->getExtension(rawFileNullExt), - ""); - - // .bAr - // interesting case - with no basename, this IS the basename, not the extension. - - ensure_equals("getExtension/e-ext", - gDirUtilp->getExtension(rawExt), - ""); - - // . - - ensure_equals("getExtension/d", - gDirUtilp->getExtension(rawDot), - ""); - - // aa/bb/cc/dd/ee[.eXt] - - ensure_equals("getExtension/no-ext", - gDirUtilp->getExtension(pathNoExt), - ""); - - ensure_equals("getExtension/ext", - gDirUtilp->getExtension(pathExt), - "ext"); - - // aa/bb/cc.dd/ee[.eXt] - - ensure_equals("getExtension/d-no-ext", - gDirUtilp->getExtension(dottedPathNoExt), - ""); - - ensure_equals("getExtension/d-ext", - gDirUtilp->getExtension(dottedPathExt), - "ext"); - } - - std::string makeTestFile( const std::string& dir, const std::string& file ) - { - std::string path = dir + file; - LLFILE* handle = LLFile::fopen( path, "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." - ensure("failed to write to test file '"+path+"'", EOF != fputs("test file", handle) ); - fclose(handle); - return path; - } - - std::string makeTestDir( const std::string& dirbase ) - { - int counter; - std::string uniqueDir; - bool foundUnused; - std::string delim = gDirUtilp->getDirDelimiter(); - - for (counter=0, foundUnused=false; !foundUnused; counter++ ) - { - char counterStr[3]; - sprintf(counterStr, "%02d", counter); - uniqueDir = dirbase + counterStr; - foundUnused = ! ( LLFile::isdir(uniqueDir) || LLFile::isfile(uniqueDir) ); - } - ensure("test directory '" + uniqueDir + "' creation failed", !LLFile::mkdir(uniqueDir)); - - return uniqueDir + delim; // HACK - apparently, the trailing delimiter is needed... - } - - static const char* DirScanFilename[5] = { "file1.abc", "file2.abc", "file1.xyz", "file2.xyz", "file1.mno" }; - - void scanTest(const std::string& directory, const std::string& pattern, bool correctResult[5]) - { - - // Scan directory and see if any file1.* files are found - std::string scanResult; - int found = 0; - bool filesFound[5] = { false, false, false, false, false }; - //std::cerr << "searching '"+directory+"' for '"+pattern+"'\n"; - - LLDirIterator iter(directory, pattern); - while ( found <= 5 && iter.next(scanResult) ) - { - found++; - //std::cerr << " found '"+scanResult+"'\n"; - int check; - for (check=0; check < 5 && ! ( scanResult == DirScanFilename[check] ); check++) - { - } - // check is now either 5 (not found) or the index of the matching name - if (check < 5) - { - ensure( "found file '"+(std::string)DirScanFilename[check]+"' twice", ! filesFound[check] ); - filesFound[check] = true; - } - else // check is 5 - should not happen - { - fail( "found unknown file '"+scanResult+"'"); - } - } - for (int i=0; i<5; i++) - { - if (correctResult[i]) - { - ensure("scan of '"+directory+"' using '"+pattern+"' did not return '"+DirScanFilename[i]+"'", filesFound[i]); - } - else - { - ensure("scan of '"+directory+"' using '"+pattern+"' incorrectly returned '"+DirScanFilename[i]+"'", !filesFound[i]); - } - } - } - - template<> template<> - void LLDirTest_object_t::test<5>() - // LLDirIterator::next - { - std::string delim = gDirUtilp->getDirDelimiter(); - std::string dirTemp = LLFile::tmpdir(); - - // Create the same 5 file names of the two directories - - std::string dir1 = makeTestDir(dirTemp + "LLDirIterator"); - std::string dir2 = makeTestDir(dirTemp + "LLDirIterator"); - std::string dir1files[5]; - std::string dir2files[5]; - for (int i=0; i<5; i++) - { - dir1files[i] = makeTestFile(dir1, DirScanFilename[i]); - dir2files[i] = makeTestFile(dir2, DirScanFilename[i]); - } - - // Scan dir1 and see if each of the 5 files is found exactly once - bool expected1[5] = { true, true, true, true, true }; - scanTest(dir1, "*", expected1); - - // Scan dir2 and see if only the 2 *.xyz files are found - bool expected2[5] = { false, false, true, true, false }; - scanTest(dir1, "*.xyz", expected2); - - // Scan dir2 and see if only the 1 *.mno file is found - bool expected3[5] = { false, false, false, false, true }; - scanTest(dir2, "*.mno", expected3); - - // Scan dir1 and see if any *.foo files are found - bool expected4[5] = { false, false, false, false, false }; - scanTest(dir1, "*.foo", expected4); - - // Scan dir1 and see if any file1.* files are found - bool expected5[5] = { true, false, true, false, true }; - scanTest(dir1, "file1.*", expected5); - - // Scan dir1 and see if any file1.* files are found - bool expected6[5] = { true, true, false, false, false }; - scanTest(dir1, "file?.abc", expected6); - - // Scan dir2 and see if any file?.x?z files are found - bool expected7[5] = { false, false, true, true, false }; - scanTest(dir2, "file?.x?z", expected7); - - // Scan dir2 and see if any file?.??c files are found - bool expected8[5] = { true, true, false, false, false }; - scanTest(dir2, "file?.??c", expected8); - scanTest(dir2, "*.??c", expected8); - - // Scan dir1 and see if any *.?n? files are found - bool expected9[5] = { false, false, false, false, true }; - scanTest(dir1, "*.?n?", expected9); - - // Scan dir1 and see if any *.???? files are found - bool expected10[5] = { false, false, false, false, false }; - scanTest(dir1, "*.????", expected10); - - // Scan dir1 and see if any ?????.* files are found - bool expected11[5] = { true, true, true, true, true }; - scanTest(dir1, "?????.*", expected11); - - // Scan dir1 and see if any ??l??.xyz files are found - bool expected12[5] = { false, false, true, true, false }; - scanTest(dir1, "??l??.xyz", expected12); - - bool expected13[5] = { true, false, true, false, false }; - scanTest(dir1, "file1.{abc,xyz}", expected13); - - bool expected14[5] = { true, true, false, false, false }; - scanTest(dir1, "file[0-9].abc", expected14); - - bool expected15[5] = { true, true, false, false, false }; - scanTest(dir1, "file[!a-z].abc", expected15); - - // clean up all test files and directories - for (int i=0; i<5; i++) - { - LLFile::remove(dir1files[i]); - LLFile::remove(dir2files[i]); - } - LLFile::rmdir(dir1); - LLFile::rmdir(dir2); - } - - template<> template<> - void LLDirTest_object_t::test<6>() - { - set_test_name("findSkinnedFilenames()"); - LLDir_Dummy lldir; - /*------------------------ "default", "en" -------------------------*/ - // Setting "default" means we shouldn't consider any "*/skins/steam" - // directories; setting "en" means we shouldn't consider any "xui/fr" - // directories. - lldir.setSkinFolder("default", "en"); - ensure_equals(lldir.getSkinFolder(), "default"); - ensure_equals(lldir.getLanguage(), "en"); - - // top-level directory of a skin isn't localized - ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS), - vec(list_of("install/skins/default/colors.xml") - ("user/skins/default/colors.xml"))); - // We should not have needed to check for skins/default/en. We should - // just "know" that SKINBASE is not localized. - lldir.ensure_not_checked("install/skins/default/en"); - - ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_default.jpeg"), - vec(list_of("install/skins/default/textures/only_default.jpeg"))); - // Nor should we have needed to check skins/default/textures/en - // because textures is known not to be localized. - lldir.ensure_not_checked("install/skins/default/textures/en"); - - StringVec expected(vec(list_of("install/skins/default/xui/en/strings.xml") - ("user/skins/default/xui/en/strings.xml"))); - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), - expected); - // The first time, we had to probe to find out whether xui was localized. - lldir.ensure_checked("install/skins/default/xui/en"); - lldir.clear_checked(); - // Now make the same call again -- should return same result -- - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), - expected); - // but this time it should remember that xui is localized. - lldir.ensure_not_checked("install/skins/default/xui/en"); - - // localized subdir with "en-us" instead of "en" - ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), - vec(list_of("install/skins/default/html/en-us/welcome.html"))); - lldir.ensure_checked("install/skins/default/html/en"); - lldir.ensure_checked("install/skins/default/html/en-us"); - lldir.clear_checked(); - ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), - vec(list_of("install/skins/default/html/en-us/welcome.html"))); - lldir.ensure_not_checked("install/skins/default/html/en"); - lldir.ensure_not_checked("install/skins/default/html/en-us"); - - ensure_equals(lldir.findSkinnedFilenames("future", "somefile.txt"), - vec(list_of("install/skins/default/future/somefile.txt"))); - // Test probing for an unrecognized unlocalized future subdir. - lldir.ensure_checked("install/skins/default/future/en"); - lldir.clear_checked(); - ensure_equals(lldir.findSkinnedFilenames("future", "somefile.txt"), - vec(list_of("install/skins/default/future/somefile.txt"))); - // Second time it should remember that future is unlocalized. - lldir.ensure_not_checked("install/skins/default/future/en"); - - // When language is set to "en", requesting an html file pulls up the - // "en-us" version -- not because it magically matches those strings, - // but because there's no "en" localization and it falls back on the - // default "en-us"! Note that it would probably still be better to - // make the default localization be "en" and allow "en-gb" (or - // whatever) localizations, which would work much more the way you'd - // expect. - ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), - vec(list_of("install/skins/default/html/en-us/welcome.html"))); - - /*------------------------ "default", "fr" -------------------------*/ - // We start being able to distinguish localized subdirs from - // unlocalized when we ask for a non-English language. - lldir.setSkinFolder("default", "fr"); - ensure_equals(lldir.getLanguage(), "fr"); - - // pass merge=true to request this filename in all relevant skins - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), - vec(list_of - ("install/skins/default/xui/en/strings.xml") - ("install/skins/default/xui/fr/strings.xml") - ("user/skins/default/xui/en/strings.xml") - ("user/skins/default/xui/fr/strings.xml"))); - - // pass (or default) merge=false to request only most specific skin - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), - vec(list_of - ("user/skins/default/xui/en/strings.xml") - ("user/skins/default/xui/fr/strings.xml"))); - - // Our dummy floater.xml has a user localization (for "fr") but no - // English override. This is a case in which CURRENT_SKIN nonetheless - // returns paths from two different skins. - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "floater.xml"), - vec(list_of - ("install/skins/default/xui/en/floater.xml") - ("user/skins/default/xui/fr/floater.xml"))); - - // Our dummy newfile.xml has an English override but no user - // localization. This is another case in which CURRENT_SKIN - // nonetheless returns paths from two different skins. - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "newfile.xml"), - vec(list_of - ("user/skins/default/xui/en/newfile.xml") - ("install/skins/default/xui/fr/newfile.xml"))); - - ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), - vec(list_of - ("install/skins/default/html/en-us/welcome.html") - ("install/skins/default/html/fr/welcome.html"))); - - /*------------------------ "default", "zh" -------------------------*/ - lldir.setSkinFolder("default", "zh"); - // Because strings.xml has only a "fr" override but no "zh" override - // in any skin, the most localized version we can find is "en". - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), - vec(list_of("user/skins/default/xui/en/strings.xml"))); - - /*------------------------- "steam", "en" --------------------------*/ - lldir.setSkinFolder("steam", "en"); - - ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS), - vec(list_of - ("install/skins/default/colors.xml") - ("install/skins/steam/colors.xml") - ("user/skins/default/colors.xml") - ("user/skins/steam/colors.xml"))); - - ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_default.jpeg"), - vec(list_of("install/skins/default/textures/only_default.jpeg"))); - - ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_steam.jpeg"), - vec(list_of("install/skins/steam/textures/only_steam.jpeg"))); - - ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_user_default.jpeg"), - vec(list_of("user/skins/default/textures/only_user_default.jpeg"))); - - ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_user_steam.jpeg"), - vec(list_of("user/skins/steam/textures/only_user_steam.jpeg"))); - - // CURRENT_SKIN - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), - vec(list_of("user/skins/steam/xui/en/strings.xml"))); - - // pass constraint=ALL_SKINS to request this filename in all relevant skins - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), - vec(list_of - ("install/skins/default/xui/en/strings.xml") - ("install/skins/steam/xui/en/strings.xml") - ("user/skins/default/xui/en/strings.xml") - ("user/skins/steam/xui/en/strings.xml"))); - - /*------------------------- "steam", "fr" --------------------------*/ - lldir.setSkinFolder("steam", "fr"); - - // pass CURRENT_SKIN to request only the most specialized files - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), - vec(list_of - ("user/skins/steam/xui/en/strings.xml") - ("user/skins/steam/xui/fr/strings.xml"))); - - // pass ALL_SKINS to request this filename in all relevant skins - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), - vec(list_of - ("install/skins/default/xui/en/strings.xml") - ("install/skins/default/xui/fr/strings.xml") - ("install/skins/steam/xui/en/strings.xml") - ("install/skins/steam/xui/fr/strings.xml") - ("user/skins/default/xui/en/strings.xml") - ("user/skins/default/xui/fr/strings.xml") - ("user/skins/steam/xui/en/strings.xml") - ("user/skins/steam/xui/fr/strings.xml"))); - } - - template<> template<> - void LLDirTest_object_t::test<7>() - { - set_test_name("add()"); - LLDir_Dummy lldir; - ensure_equals("both empty", lldir.add("", ""), ""); - ensure_equals("path empty", lldir.add("", "b"), "b"); - ensure_equals("name empty", lldir.add("a", ""), "a"); - ensure_equals("both simple", lldir.add("a", "b"), "a/b"); - ensure_equals("name leading slash", lldir.add("a", "/b"), "a/b"); - ensure_equals("path trailing slash", lldir.add("a/", "b"), "a/b"); - ensure_equals("both bring slashes", lldir.add("a/", "/b"), "a/b"); - } -} diff --git a/indra/llcache/tests/lldiriterator_test.cpp b/indra/llcache/tests/lldiriterator_test.cpp deleted file mode 100644 index a65e3dada5..0000000000 --- a/indra/llcache/tests/lldiriterator_test.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @file lldiriterator_test.cpp - * @date 2011-06 - * @brief LLDirIterator test cases. - * - * $LicenseInfo:firstyear=2011&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2011, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only., - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "lltut.h" -#include "../lldiriterator.h" - - -namespace tut -{ - - struct LLDirIteratorFixture - { - LLDirIteratorFixture() - { - } - }; - typedef test_group LLDirIteratorTest_factory; - typedef LLDirIteratorTest_factory::object LLDirIteratorTest_t; - LLDirIteratorTest_factory tf("LLDirIterator"); - - /* - CHOP-662 was originally introduced to deal with crashes deleting files from - a directory (VWR-25500). However, this introduced a crash looking for - old chat logs as the glob_to_regex function in lldiriterator wasn't escaping lots of regexp characters - */ - void test_chop_662(void) - { - // Check a selection of bad group names from the crash reports - LLDirIterator iter(".","+bad-group-name]+?\?-??.*"); - LLDirIterator iter1(".","))--@---bad-group-name2((?\?-??.*\\.txt"); - LLDirIterator iter2(".","__^v--x)Cuide d sua vida(x--v^__?\?-??.*"); - } - - template<> template<> - void LLDirIteratorTest_t::test<1>() - { - test_chop_662(); - } - -} diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt index e236a307c2..d90ffb5543 100644 --- a/indra/llcharacter/CMakeLists.txt +++ b/indra/llcharacter/CMakeLists.txt @@ -6,14 +6,14 @@ include(00-Common) include(LLCommon) include(LLMath) include(LLMessage) -include(LLCache) +include(LLFileSystem) include(LLXML) include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ) include_directories(SYSTEM @@ -85,6 +85,6 @@ target_link_libraries( ${LLCOMMON_LIBRARIES} ${LLMATH_LIBRARIES} ${LLMESSAGE_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLXML_LIBRARIES} ) diff --git a/indra/llcrashlogger/CMakeLists.txt b/indra/llcrashlogger/CMakeLists.txt index 040a0e846c..d70a1e0fb0 100644 --- a/indra/llcrashlogger/CMakeLists.txt +++ b/indra/llcrashlogger/CMakeLists.txt @@ -7,7 +7,7 @@ include(LLCoreHttp) include(LLCommon) include(LLMath) include(LLMessage) -include(LLCache) +include(LLFileSystem) include(LLXML) include_directories( @@ -15,7 +15,7 @@ include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ) include_directories(SYSTEM diff --git a/indra/llfilesystem/CMakeLists.txt b/indra/llfilesystem/CMakeLists.txt new file mode 100644 index 0000000000..4af14d6d3a --- /dev/null +++ b/indra/llfilesystem/CMakeLists.txt @@ -0,0 +1,98 @@ +# -*- cmake -*- + +project(llfilesystem) + +include(00-Common) +include(LLCommon) +include(UnixInstall) + +include_directories( + ${LLCOMMON_INCLUDE_DIRS} + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) + +set(llfilesystem_SOURCE_FILES + lldir.cpp + lldiriterator.cpp + lllfsthread.cpp + lldiskcache.cpp + ) + +set(llfilesystem_HEADER_FILES + CMakeLists.txt + + lldir.h + lldirguard.h + lldiriterator.h + lllfsthread.h + lldiskcache.h + ) + +if (DARWIN) + LIST(APPEND llfilesystem_SOURCE_FILES lldir_utils_objc.mm) + LIST(APPEND llfilesystem_SOURCE_FILES lldir_utils_objc.h) + LIST(APPEND llfilesystem_SOURCE_FILES lldir_mac.cpp) + LIST(APPEND llfilesystem_HEADER_FILES lldir_mac.h) +endif (DARWIN) + +if (LINUX) + LIST(APPEND llfilesystem_SOURCE_FILES lldir_linux.cpp) + LIST(APPEND llfilesystem_HEADER_FILES lldir_linux.h) + + if (INSTALL) + set_source_files_properties(lldir_linux.cpp + PROPERTIES COMPILE_FLAGS + "-DAPP_RO_DATA_DIR=\\\"${APP_SHARE_DIR}\\\"" + ) + endif (INSTALL) +endif (LINUX) + +if (WINDOWS) + LIST(APPEND llfilesystem_SOURCE_FILES lldir_win32.cpp) + LIST(APPEND llfilesystem_HEADER_FILES lldir_win32.h) +endif (WINDOWS) + +set_source_files_properties(${llfilesystem_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND llfilesystem_SOURCE_FILES ${llfilesystem_HEADER_FILES}) + +add_library (llfilesystem ${llfilesystem_SOURCE_FILES}) + +set(cache_BOOST_LIBRARIES + ${BOOST_FILESYSTEM_LIBRARY} + ${BOOST_SYSTEM_LIBRARY} + ) + +target_link_libraries(llfilesystem + ${LLCOMMON_LIBRARIES} + ${cache_BOOST_LIBRARIES} + ) + +if (DARWIN) + include(CMakeFindFrameworks) + find_library(COCOA_LIBRARY Cocoa) + target_link_libraries(llfilesystem ${COCOA_LIBRARY}) +endif (DARWIN) + + +# Add tests +if (LL_TESTS) + include(LLAddBuildTest) + # UNIT TESTS + SET(llfilesystem_TEST_SOURCE_FILES + lldiriterator.cpp + ) + + set_source_files_properties(lldiriterator.cpp + PROPERTIES + LL_TEST_ADDITIONAL_LIBRARIES "${cache_BOOST_LIBRARIES}" + ) + LL_ADD_PROJECT_UNIT_TESTS(llfilesystem "${llfilesystem_TEST_SOURCE_FILES}") + + # INTEGRATION TESTS + set(test_libs llmath llcommon llfilesystem ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) + + # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests. + LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}") +endif (LL_TESTS) diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp new file mode 100644 index 0000000000..10fbc06c61 --- /dev/null +++ b/indra/llfilesystem/lldir.cpp @@ -0,0 +1,1134 @@ +/** + * @file lldir.cpp + * @brief implementation of directory utilities base class + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#if !LL_WINDOWS +#include +#include +#include +#else +#include +#endif + +#include "lldir.h" + +#include "llerror.h" +#include "lltimer.h" // ms_sleep() +#include "lluuid.h" + +#include "lldiriterator.h" +#include "stringize.h" +#include "llstring.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using boost::assign::list_of; +using boost::assign::map_list_of; + +#if LL_WINDOWS +#include "lldir_win32.h" +LLDir_Win32 gDirUtil; +#elif LL_DARWIN +#include "lldir_mac.h" +LLDir_Mac gDirUtil; +#elif LL_SOLARIS +#include "lldir_solaris.h" +LLDir_Solaris gDirUtil; +#else +#include "lldir_linux.h" +LLDir_Linux gDirUtil; +#endif + +LLDir *gDirUtilp = (LLDir *)&gDirUtil; + +/// Values for findSkinnedFilenames(subdir) parameter +const char + *LLDir::XUI = "xui", + *LLDir::TEXTURES = "textures", + *LLDir::SKINBASE = ""; + +static const char* const empty = ""; +std::string LLDir::sDumpDir = ""; + +LLDir::LLDir() +: mAppName(""), + mExecutablePathAndName(""), + mExecutableFilename(""), + mExecutableDir(""), + mAppRODataDir(""), + mOSUserDir(""), + mOSUserAppDir(""), + mLindenUserDir(""), + mOSCacheDir(""), + mCAFile(""), + mTempDir(""), + mDirDelimiter("/"), // fallback to forward slash if not overridden + mLanguage("en"), + mUserName("undefined") +{ +} + +LLDir::~LLDir() +{ +} + +std::vector LLDir::getFilesInDir(const std::string &dirname) +{ + //Returns a vector of fullpath filenames. + +#ifdef LL_WINDOWS // or BOOST_WINDOWS_API + boost::filesystem::path p(utf8str_to_utf16str(dirname)); +#else + boost::filesystem::path p(dirname); +#endif + + std::vector v; + + if (exists(p)) + { + if (is_directory(p)) + { + boost::filesystem::directory_iterator end_iter; + for (boost::filesystem::directory_iterator dir_itr(p); + dir_itr != end_iter; + ++dir_itr) + { + if (boost::filesystem::is_regular_file(dir_itr->status())) + { + v.push_back(dir_itr->path().filename().string()); + } + } + } + } + return v; +} + +S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) +{ + S32 count = 0; + std::string filename; + std::string fullpath; + S32 result; + + // File masks starting with "/" will match nothing, so we consider them invalid. + if (LLStringUtil::startsWith(mask, getDirDelimiter())) + { + LL_WARNS() << "Invalid file mask: " << mask << LL_ENDL; + llassert(!"Invalid file mask"); + } + + LLDirIterator iter(dirname, mask); + while (iter.next(filename)) + { + fullpath = add(dirname, filename); + + if(LLFile::isdir(fullpath)) + { + // skipping directory traversal filenames + count++; + continue; + } + + S32 retry_count = 0; + while (retry_count < 5) + { + if (0 != LLFile::remove(fullpath)) + { + retry_count++; + result = errno; + LL_WARNS() << "Problem removing " << fullpath << " - errorcode: " + << result << " attempt " << retry_count << LL_ENDL; + + if(retry_count >= 5) + { + LL_WARNS() << "Failed to remove " << fullpath << LL_ENDL ; + return count ; + } + + ms_sleep(100); + } + else + { + if (retry_count) + { + LL_WARNS() << "Successfully removed " << fullpath << LL_ENDL; + } + break; + } + } + count++; + } + return count; +} + +U32 LLDir::deleteDirAndContents(const std::string& dir_name) +{ + //Removes the directory and its contents. Returns number of files deleted. + + U32 num_deleted = 0; + + try + { +#ifdef LL_WINDOWS // or BOOST_WINDOWS_API + boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name)); +#else + boost::filesystem::path dir_path(dir_name); +#endif + + if (boost::filesystem::exists (dir_path)) + { + if (!boost::filesystem::is_empty (dir_path)) + { // Directory has content + num_deleted = boost::filesystem::remove_all (dir_path); + } + else + { // Directory is empty + boost::filesystem::remove (dir_path); + } + } + } + catch (boost::filesystem::filesystem_error &er) + { + LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL; + } + return num_deleted; +} + +const std::string LLDir::findFile(const std::string &filename, + const std::string& searchPath1, + const std::string& searchPath2, + const std::string& searchPath3) const +{ + std::vector search_paths; + search_paths.push_back(searchPath1); + search_paths.push_back(searchPath2); + search_paths.push_back(searchPath3); + return findFile(filename, search_paths); +} + +const std::string LLDir::findFile(const std::string& filename, const std::vector search_paths) const +{ + std::vector::const_iterator search_path_iter; + for (search_path_iter = search_paths.begin(); + search_path_iter != search_paths.end(); + ++search_path_iter) + { + if (!search_path_iter->empty()) + { + std::string filename_and_path = (*search_path_iter); + if (!filename.empty()) + { + filename_and_path += getDirDelimiter() + filename; + } + if (fileExists(filename_and_path)) + { + return filename_and_path; + } + } + } + return ""; +} + + +const std::string &LLDir::getExecutablePathAndName() const +{ + return mExecutablePathAndName; +} + +const std::string &LLDir::getExecutableFilename() const +{ + return mExecutableFilename; +} + +const std::string &LLDir::getExecutableDir() const +{ + return mExecutableDir; +} + +const std::string &LLDir::getWorkingDir() const +{ + return mWorkingDir; +} + +const std::string &LLDir::getAppName() const +{ + return mAppName; +} + +const std::string &LLDir::getAppRODataDir() const +{ + return mAppRODataDir; +} + +const std::string &LLDir::getOSUserDir() const +{ + return mOSUserDir; +} + +const std::string &LLDir::getOSUserAppDir() const +{ + return mOSUserAppDir; +} + +const std::string &LLDir::getLindenUserDir() const +{ + if (mLindenUserDir.empty()) + { + LL_DEBUGS() << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << LL_ENDL; + } + + return mLindenUserDir; +} + +const std::string& LLDir::getChatLogsDir() const +{ + return mChatLogsDir; +} + +void LLDir::setDumpDir( const std::string& path ) +{ + LLDir::sDumpDir = path; + if (LLStringUtil::endsWith(sDumpDir, mDirDelimiter)) + { + sDumpDir.erase(sDumpDir.size() - mDirDelimiter.size()); + } +} + +const std::string &LLDir::getDumpDir() const +{ + if (sDumpDir.empty() ) + { + LLUUID uid; + uid.generate(); + + sDumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "") + + "dump-" + uid.asString(); + + dir_exists_or_crash(sDumpDir); + } + + return LLDir::sDumpDir; +} + +const std::string &LLDir::getPerAccountChatLogsDir() const +{ + return mPerAccountChatLogsDir; +} + +const std::string &LLDir::getTempDir() const +{ + return mTempDir; +} + +const std::string LLDir::getCacheDir(bool get_default) const +{ + if (mCacheDir.empty() || get_default) + { + if (!mDefaultCacheDir.empty()) + { // Set at startup - can't set here due to const API + return mDefaultCacheDir; + } + + std::string res = buildSLOSCacheDir(); + return res; + } + else + { + return mCacheDir; + } +} + +// Return the default cache directory +std::string LLDir::buildSLOSCacheDir() const +{ + std::string res; + if (getOSCacheDir().empty()) + { + if (getOSUserAppDir().empty()) + { + res = "data"; + } + else + { + res = add(getOSUserAppDir(), "cache"); + } + } + else + { + res = add(getOSCacheDir(), "SecondLife"); + } + return res; +} + + + +const std::string &LLDir::getOSCacheDir() const +{ + return mOSCacheDir; +} + + +const std::string &LLDir::getCAFile() const +{ + return mCAFile; +} + +const std::string &LLDir::getDirDelimiter() const +{ + return mDirDelimiter; +} + +const std::string& LLDir::getDefaultSkinDir() const +{ + return mDefaultSkinDir; +} + +const std::string &LLDir::getSkinDir() const +{ + return mSkinDir; +} + +const std::string &LLDir::getUserDefaultSkinDir() const +{ + return mUserDefaultSkinDir; +} + +const std::string &LLDir::getUserSkinDir() const +{ + return mUserSkinDir; +} + +const std::string LLDir::getSkinBaseDir() const +{ + return mSkinBaseDir; +} + +const std::string &LLDir::getLLPluginDir() const +{ + return mLLPluginDir; +} + +const std::string &LLDir::getUserName() const +{ + return mUserName; +} + +static std::string ELLPathToString(ELLPath location) +{ + typedef std::map ELLPathMap; +#define ENT(symbol) (symbol, #symbol) + static const ELLPathMap sMap = map_list_of + ENT(LL_PATH_NONE) + ENT(LL_PATH_USER_SETTINGS) + ENT(LL_PATH_APP_SETTINGS) + ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet + ENT(LL_PATH_CACHE) + ENT(LL_PATH_CHARACTER) + ENT(LL_PATH_HELP) + ENT(LL_PATH_LOGS) + ENT(LL_PATH_TEMP) + ENT(LL_PATH_SKINS) + ENT(LL_PATH_TOP_SKIN) + ENT(LL_PATH_CHAT_LOGS) + ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS) + ENT(LL_PATH_USER_SKIN) + ENT(LL_PATH_LOCAL_ASSETS) + ENT(LL_PATH_EXECUTABLE) + ENT(LL_PATH_DEFAULT_SKIN) + ENT(LL_PATH_FONTS) + ENT(LL_PATH_LAST) + ; +#undef ENT + + ELLPathMap::const_iterator found = sMap.find(location); + if (found != sMap.end()) + return found->second; + return STRINGIZE("Invalid ELLPath value " << location); +} + +std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const +{ + return getExpandedFilename(location, "", filename); +} + +std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir, const std::string& filename) const +{ + return getExpandedFilename(location, "", subdir, filename); +} + +std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir1, const std::string& subdir2, const std::string& in_filename) const +{ + std::string prefix; + switch (location) + { + case LL_PATH_NONE: + // Do nothing + break; + + case LL_PATH_APP_SETTINGS: + prefix = add(getAppRODataDir(), "app_settings"); + break; + + case LL_PATH_CHARACTER: + prefix = add(getAppRODataDir(), "character"); + break; + + case LL_PATH_HELP: + prefix = "help"; + break; + + case LL_PATH_CACHE: + prefix = getCacheDir(); + break; + + case LL_PATH_DUMP: + prefix=getDumpDir(); + break; + + case LL_PATH_USER_SETTINGS: + prefix = add(getOSUserAppDir(), "user_settings"); + break; + + case LL_PATH_PER_SL_ACCOUNT: + prefix = getLindenUserDir(); + if (prefix.empty()) + { + // if we're asking for the per-SL-account directory but we haven't + // logged in yet (or otherwise don't know the account name from + // which to build this string), then intentionally return a blank + // string to the caller and skip the below warning about a blank + // prefix. + LL_DEBUGS("LLDir") << "getLindenUserDir() not yet set: " + << ELLPathToString(location) + << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename + << "' => ''" << LL_ENDL; + return std::string(); + } + break; + + case LL_PATH_CHAT_LOGS: + prefix = getChatLogsDir(); + break; + + case LL_PATH_PER_ACCOUNT_CHAT_LOGS: + prefix = getPerAccountChatLogsDir(); + if (prefix.empty()) + { + // potentially directory was not set yet + // intentionally return a blank string to the caller + LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL; + return std::string(); + } + break; + + case LL_PATH_LOGS: + prefix = add(getOSUserAppDir(), "logs"); + break; + + case LL_PATH_TEMP: + prefix = getTempDir(); + break; + + case LL_PATH_TOP_SKIN: + prefix = getSkinDir(); + break; + + case LL_PATH_DEFAULT_SKIN: + prefix = getDefaultSkinDir(); + break; + + case LL_PATH_USER_SKIN: + prefix = getUserSkinDir(); + break; + + case LL_PATH_SKINS: + prefix = getSkinBaseDir(); + break; + + case LL_PATH_LOCAL_ASSETS: + prefix = add(getAppRODataDir(), "local_assets"); + break; + + case LL_PATH_EXECUTABLE: + prefix = getExecutableDir(); + break; + + case LL_PATH_FONTS: + prefix = add(getAppRODataDir(), "fonts"); + break; + + default: + llassert(0); + } + + if (prefix.empty()) + { + LL_WARNS() << ELLPathToString(location) + << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename + << "': prefix is empty, possible bad filename" << LL_ENDL; + } + + std::string expanded_filename = add(prefix, subdir1, subdir2); + if (expanded_filename.empty() && in_filename.empty()) + { + return ""; + } + // Use explicit concatenation here instead of another add() call. Callers + // passing in_filename as "" expect to obtain a pathname ending with + // mDirSeparator so they can later directly concatenate with a specific + // filename. A caller using add() doesn't care, but there's still code + // loose in the system that uses std::string::operator+(). + expanded_filename += mDirDelimiter; + expanded_filename += in_filename; + + LL_DEBUGS("LLDir") << ELLPathToString(location) + << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename + << "' => '" << expanded_filename << "'" << LL_ENDL; + return expanded_filename; +} + +std::string LLDir::getBaseFileName(const std::string& filepath, bool strip_exten) const +{ + std::size_t offset = filepath.find_last_of(getDirDelimiter()); + offset = (offset == std::string::npos) ? 0 : offset+1; + std::string res = filepath.substr(offset, std::string::npos); + if (strip_exten) + { + offset = res.find_last_of('.'); + if (offset != std::string::npos && + offset != 0) // if basename STARTS with '.', don't strip + { + res = res.substr(0, offset); + } + } + return res; +} + +std::string LLDir::getDirName(const std::string& filepath) const +{ + std::size_t offset = filepath.find_last_of(getDirDelimiter()); + S32 len = (offset == std::string::npos) ? 0 : offset; + std::string dirname = filepath.substr(0, len); + return dirname; +} + +std::string LLDir::getExtension(const std::string& filepath) const +{ + if (filepath.empty()) + return std::string(); + std::string basename = getBaseFileName(filepath, false); + std::size_t offset = basename.find_last_of('.'); + std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1); + LLStringUtil::toLower(exten); + return exten; +} + +std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint) const +{ + // This implementation is basically just as described in the declaration comments. + std::vector found(findSkinnedFilenames(subdir, filename, constraint)); + if (found.empty()) + { + return ""; + } + return found.front(); +} + +std::string LLDir::findSkinnedFilename(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint) const +{ + // This implementation is basically just as described in the declaration comments. + std::vector found(findSkinnedFilenames(subdir, filename, constraint)); + if (found.empty()) + { + return ""; + } + return found.back(); +} + +// This method exists because the two code paths for +// findSkinnedFilenames(ALL_SKINS) and findSkinnedFilenames(CURRENT_SKIN) must +// generate the list of candidate pathnames in identical ways. The only +// difference is in the body of the inner loop. +template +void LLDir::walkSearchSkinDirs(const std::string& subdir, + const std::vector& subsubdirs, + const std::string& filename, + const FUNCTION& function) const +{ + BOOST_FOREACH(std::string skindir, mSearchSkinDirs) + { + std::string subdir_path(add(skindir, subdir)); + BOOST_FOREACH(std::string subsubdir, subsubdirs) + { + std::string full_path(add(subdir_path, subsubdir, filename)); + if (fileExists(full_path)) + { + function(subsubdir, full_path); + } + } + } +} + +// ridiculous little helper function that should go away when we can use lambda +inline void push_back(std::vector& vector, const std::string& value) +{ + vector.push_back(value); +} + +typedef std::map StringMap; +// ridiculous little helper function that should go away when we can use lambda +inline void store_in_map(StringMap& map, const std::string& key, const std::string& value) +{ + map[key] = value; +} + +std::vector LLDir::findSkinnedFilenames(const std::string& subdir, + const std::string& filename, + ESkinConstraint constraint) const +{ + // Recognize subdirs that have no localization. + static const std::set sUnlocalized = list_of + ("") // top-level directory not localized + ("textures") // textures not localized + ; + + LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename + << "', constraint " + << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS") + << LL_ENDL; + + // Build results vector. + std::vector results; + // Disallow filenames that may escape subdir + if (filename.find("..") != std::string::npos) + { + LL_WARNS("LLDir") << "Ignoring potentially relative filename '" << filename << "'" << LL_ENDL; + return results; + } + + // Cache the default language directory for each subdir we've encountered. + // A cache entry whose value is the empty string means "not localized, + // don't bother checking again." + static StringMap sLocalized; + + // Check whether we've already discovered if this subdir is localized. + StringMap::const_iterator found = sLocalized.find(subdir); + if (found == sLocalized.end()) + { + // We have not yet determined that. Is it one of the subdirs "known" + // to be unlocalized? + if (sUnlocalized.find(subdir) != sUnlocalized.end()) + { + // This subdir is known to be unlocalized. Remember that. + found = sLocalized.insert(StringMap::value_type(subdir, "")).first; + } + else + { + // We do not recognize this subdir. Investigate. + std::string subdir_path(add(getDefaultSkinDir(), subdir)); + if (fileExists(add(subdir_path, "en"))) + { + // defaultSkinDir/subdir contains subdir "en". That's our + // default language; this subdir is localized. + found = sLocalized.insert(StringMap::value_type(subdir, "en")).first; + } + else if (fileExists(add(subdir_path, "en-us"))) + { + // defaultSkinDir/subdir contains subdir "en-us" but not "en". + // Set as default language; this subdir is localized. + found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first; + } + else + { + // defaultSkinDir/subdir contains neither "en" nor "en-us". + // Assume it's not localized. Remember that assumption. + found = sLocalized.insert(StringMap::value_type(subdir, "")).first; + } + } + } + // Every code path above should have resulted in 'found' becoming a valid + // iterator to an entry in sLocalized. + llassert(found != sLocalized.end()); + + // Now -- is this subdir localized, or not? The answer determines what + // subdirectories we check (under subdir) for the requested filename. + std::vector subsubdirs; + if (found->second.empty()) + { + // subdir is not localized. filename should be located directly within it. + subsubdirs.push_back(""); + } + else + { + // subdir is localized, and found->second is the default language + // directory within it. Check both the default language and the + // current language -- if it differs from the default, of course. + subsubdirs.push_back(found->second); + if (mLanguage != found->second) + { + subsubdirs.push_back(mLanguage); + } + } + + // The process we use depends on 'constraint'. + if (constraint != CURRENT_SKIN) // meaning ALL_SKINS + { + // ALL_SKINS is simpler: just return every pathname generated by + // walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its + // FUNCTION the subsubdir as well as the full pathname. We just want + // the full pathname. + walkSearchSkinDirs(subdir, subsubdirs, filename, + boost::bind(push_back, boost::ref(results), _2)); + } + else // CURRENT_SKIN + { + // CURRENT_SKIN turns out to be a bit of a misnomer because we might + // still return files from two different skins. In any case, this + // value of 'constraint' means we will return at most two paths: one + // for the default language, one for the current language (supposing + // those differ). + // It is important to allow a user to override only the localization + // for a particular file, for all viewer installs, without also + // overriding the default-language file. + // It is important to allow a user to override only the default- + // language file, for all viewer installs, without also overriding the + // applicable localization of that file. + // Therefore, treat the default language and the current language as + // two separate cases. For each, capture the most-specialized file + // that exists. + // Use a map keyed by subsubdir (i.e. language code). This allows us + // to handle the case of a single subsubdirs entry with the same logic + // that handles two. For every real file path generated by + // walkSearchSkinDirs(), update the map entry for its subsubdir. + StringMap path_for; + walkSearchSkinDirs(subdir, subsubdirs, filename, + boost::bind(store_in_map, boost::ref(path_for), _1, _2)); + // Now that we have a path for each of the default language and the + // current language, copy them -- in proper order -- into results. + // Don't drive this by walking the map itself: it matters that we + // generate results in the same order as subsubdirs. + BOOST_FOREACH(std::string subsubdir, subsubdirs) + { + StringMap::const_iterator found(path_for.find(subsubdir)); + if (found != path_for.end()) + { + results.push_back(found->second); + } + } + } + + LL_DEBUGS("LLDir") << empty; + const char* comma = ""; + BOOST_FOREACH(std::string path, results) + { + LL_CONT << comma << "'" << path << "'"; + comma = ", "; + } + LL_CONT << LL_ENDL; + + return results; +} + +std::string LLDir::getTempFilename() const +{ + LLUUID random_uuid; + std::string uuid_str; + + random_uuid.generate(); + random_uuid.toString(uuid_str); + + return add(getTempDir(), uuid_str + ".tmp"); +} + +// static +std::string LLDir::getScrubbedFileName(const std::string uncleanFileName) +{ + std::string name(uncleanFileName); + const std::string illegalChars(getForbiddenFileChars()); + // replace any illegal file chars with and underscore '_' + for( unsigned int i = 0; i < illegalChars.length(); i++ ) + { + int j = -1; + while((j = name.find(illegalChars[i])) > -1) + { + name[j] = '_'; + } + } + return name; +} + +// static +std::string LLDir::getForbiddenFileChars() +{ + return "\\/:*?\"<>|"; +} + +void LLDir::setLindenUserDir(const std::string &username) +{ + // if the username isn't set, that's bad + if (!username.empty()) + { + // some platforms have case-sensitive filesystems, so be + // utterly consistent with our firstname/lastname case. + std::string userlower(username); + LLStringUtil::toLower(userlower); + LLStringUtil::replaceChar(userlower, ' ', '_'); + mLindenUserDir = add(getOSUserAppDir(), userlower); + } + else + { + LL_ERRS() << "NULL name for LLDir::setLindenUserDir" << LL_ENDL; + } + + dumpCurrentDirectories(); +} + +void LLDir::setChatLogsDir(const std::string &path) +{ + if (!path.empty() ) + { + mChatLogsDir = path; + } + else + { + LL_WARNS() << "Invalid name for LLDir::setChatLogsDir" << LL_ENDL; + } +} + +void LLDir::updatePerAccountChatLogsDir() +{ + mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName); +} + +void LLDir::setPerAccountChatLogsDir(const std::string &username) +{ + // if both first and last aren't set, assume we're grabbing the cached dir + if (!username.empty()) + { + // some platforms have case-sensitive filesystems, so be + // utterly consistent with our firstname/lastname case. + std::string userlower(username); + LLStringUtil::toLower(userlower); + LLStringUtil::replaceChar(userlower, ' ', '_'); + + mUserName = userlower; + updatePerAccountChatLogsDir(); + } + else + { + LL_ERRS() << "NULL name for LLDir::setPerAccountChatLogsDir" << LL_ENDL; + } +} + +void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language) +{ + LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'" + << LL_ENDL; + mSkinName = skin_folder; + mLanguage = language; + + // This method is called multiple times during viewer initialization. Each + // time it's called, reset mSearchSkinDirs. + mSearchSkinDirs.clear(); + + // base skin which is used as fallback for all skinned files + // e.g. c:\program files\secondlife\skins\default + mDefaultSkinDir = getSkinBaseDir(); + append(mDefaultSkinDir, "default"); + // This is always the most general of the search skin directories. + addSearchSkinDir(mDefaultSkinDir); + + mSkinDir = getSkinBaseDir(); + append(mSkinDir, skin_folder); + // Next level of generality is a skin installed with the viewer. + addSearchSkinDir(mSkinDir); + + // user modifications to skins, current and default + // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle + mUserSkinDir = getOSUserAppDir(); + append(mUserSkinDir, "skins"); + mUserDefaultSkinDir = mUserSkinDir; + append(mUserDefaultSkinDir, "default"); + append(mUserSkinDir, skin_folder); + // Next level of generality is user modifications to default skin... + addSearchSkinDir(mUserDefaultSkinDir); + // then user-defined skins. + addSearchSkinDir(mUserSkinDir); +} + +void LLDir::addSearchSkinDir(const std::string& skindir) +{ + if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end()) + { + LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL; + mSearchSkinDirs.push_back(skindir); + } +} + +std::string LLDir::getSkinFolder() const +{ + return mSkinName; +} + +std::string LLDir::getLanguage() const +{ + return mLanguage; +} + +bool LLDir::setCacheDir(const std::string &path) +{ + if (path.empty() ) + { + // reset to default + mCacheDir = ""; + return true; + } + else + { + LLFile::mkdir(path); + std::string tempname = add(path, "temp"); + LLFILE* file = LLFile::fopen(tempname,"wt"); + if (file) + { + fclose(file); + LLFile::remove(tempname); + mCacheDir = path; + return true; + } + return false; + } +} + +void LLDir::dumpCurrentDirectories(LLError::ELevel level) +{ + LL_VLOGS(level, "AppInit","Directories") << "Current Directories:" << LL_ENDL; + + LL_VLOGS(level, "AppInit", "Directories") << " CurPath: " << getCurPath() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " AppName: " << getAppName() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " ExecutableFilename: " << getExecutableFilename() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " ExecutableDir: " << getExecutableDir() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " ExecutablePathAndName: " << getExecutablePathAndName() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " WorkingDir: " << getWorkingDir() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " AppRODataDir: " << getAppRODataDir() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " OSUserDir: " << getOSUserDir() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " OSUserAppDir: " << getOSUserAppDir() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " TempDir: " << getTempDir() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " CAFile: " << getCAFile() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL; + LL_VLOGS(level, "AppInit", "Directories") << " SkinDir: " << getSkinDir() << LL_ENDL; +} + +void LLDir::append(std::string& destpath, const std::string& name) const +{ + // Delegate question of whether we need a separator to helper method. + SepOff sepoff(needSep(destpath, name)); + if (sepoff.first) // do we need a separator? + { + destpath += mDirDelimiter; + } + // If destpath ends with a separator, AND name starts with one, skip + // name's leading separator. + destpath += name.substr(sepoff.second); +} + +LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) const +{ + if (path.empty() || name.empty()) + { + // If either path or name are empty, we do not need a separator + // between them. + return SepOff(false, 0); + } + // Here we know path and name are both non-empty. But if path already ends + // with a separator, or if name already starts with a separator, we need + // not add one. + std::string::size_type seplen(mDirDelimiter.length()); + bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter); + bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter); + if ((! path_ends_sep) && (! name_starts_sep)) + { + // If neither path nor name brings a separator to the junction, then + // we need one. + return SepOff(true, 0); + } + if (path_ends_sep && name_starts_sep) + { + // But if BOTH path and name bring a separator, we need not add one. + // Moreover, we should actually skip the leading separator of 'name'. + return SepOff(false, (unsigned short)seplen); + } + // Here we know that either path_ends_sep or name_starts_sep is true -- + // but not both. So don't add a separator, and don't skip any characters: + // simple concatenation will do the trick. + return SepOff(false, 0); +} + +void dir_exists_or_crash(const std::string &dir_name) +{ +#if LL_WINDOWS + // *FIX: lame - it doesn't do the same thing on windows. not so + // important since we don't deploy simulator to windows boxes. + LLFile::mkdir(dir_name, 0700); +#else + struct stat dir_stat; + if(0 != LLFile::stat(dir_name, &dir_stat)) + { + S32 stat_rv = errno; + if(ENOENT == stat_rv) + { + if(0 != LLFile::mkdir(dir_name, 0700)) // octal + { + LL_ERRS() << "Unable to create directory: " << dir_name << LL_ENDL; + } + } + else + { + LL_ERRS() << "Unable to stat: " << dir_name << " errno = " << stat_rv + << LL_ENDL; + } + } + else + { + // data_dir exists, make sure it's a directory. + if(!S_ISDIR(dir_stat.st_mode)) + { + LL_ERRS() << "Data directory collision: " << dir_name << LL_ENDL; + } + } +#endif +} diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h new file mode 100644 index 0000000000..38e204ef04 --- /dev/null +++ b/indra/llfilesystem/lldir.h @@ -0,0 +1,280 @@ +/** + * @file lldir.h + * @brief Definition of directory utilities class + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDIR_H +#define LL_LLDIR_H + +#if LL_SOLARIS +#include +#define MAX_PATH MAXPATHLEN +#endif + +// these numbers are read from settings_files.xml, so we need to be explicit +typedef enum ELLPath +{ + LL_PATH_NONE = 0, + LL_PATH_USER_SETTINGS = 1, + LL_PATH_APP_SETTINGS = 2, + LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet + LL_PATH_CACHE = 4, + LL_PATH_CHARACTER = 5, + LL_PATH_HELP = 6, + LL_PATH_LOGS = 7, + LL_PATH_TEMP = 8, + LL_PATH_SKINS = 9, + LL_PATH_TOP_SKIN = 10, + LL_PATH_CHAT_LOGS = 11, + LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12, + LL_PATH_USER_SKIN = 14, + LL_PATH_LOCAL_ASSETS = 15, + LL_PATH_EXECUTABLE = 16, + LL_PATH_DEFAULT_SKIN = 17, + LL_PATH_FONTS = 18, + LL_PATH_DUMP = 19, + LL_PATH_LAST +} ELLPath; + +/// Directory operations +class LLDir +{ + public: + LLDir(); + virtual ~LLDir(); + + // app_name - Usually SecondLife, used for creating settings directories + // in OS-specific location, such as C:\Documents and Settings + // app_read_only_data_dir - Usually the source code directory, used + // for test applications to read newview data files. + virtual void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir = "") = 0; + + virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask); + U32 deleteDirAndContents(const std::string& dir_name); + std::vector getFilesInDir(const std::string &dirname); +// pure virtual functions + virtual std::string getCurPath() = 0; + virtual bool fileExists(const std::string &filename) const = 0; + + 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; + + virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell + virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so') + + const std::string &getExecutablePathAndName() const; // Full pathname of the executable + const std::string &getAppName() const; // install directory under progams/ ie "SecondLife" + const std::string &getExecutableDir() const; // Directory where the executable is located + const std::string &getExecutableFilename() const;// Filename of .exe + const std::string &getWorkingDir() const; // Current working directory + const std::string &getAppRODataDir() const; // Location of read-only data files + const std::string &getOSUserDir() const; // Location of the os-specific user dir + const std::string &getOSUserAppDir() const; // Location of the os-specific user app dir + const std::string &getLindenUserDir() const; // Location of the Linden user dir. + const std::string &getChatLogsDir() const; // Location of the chat logs dir. + const std::string &getDumpDir() const; // Location of the per-run dump dir. + const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir. + const std::string &getTempDir() const; // Common temporary directory + const std::string getCacheDir(bool get_default = false) const; // Location of the cache. + const std::string &getOSCacheDir() const; // location of OS-specific cache folder (may be empty string) + const std::string &getCAFile() const; // File containing TLS certificate authorities + const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':') + const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default + const std::string &getSkinDir() const; // User-specified skin folder. + const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin + const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin + const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins + const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell + const std::string &getUserName() const; + + // Expanded filename + std::string getExpandedFilename(ELLPath location, const std::string &filename) const; + std::string getExpandedFilename(ELLPath location, const std::string &subdir, const std::string &filename) const; + std::string getExpandedFilename(ELLPath location, const std::string &subdir1, const std::string &subdir2, const std::string &filename) const; + + // Base and Directory name extraction + std::string getBaseFileName(const std::string& filepath, bool strip_exten = false) const; + std::string getDirName(const std::string& filepath) const; + std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav" + + // these methods search the various skin paths for the specified file in the following order: + // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir() + /// param value for findSkinnedFilenames(), explained below + enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS }; + /** + * Given a filename within skin, return an ordered sequence of paths to + * search. Nonexistent files will be filtered out -- which means that the + * vector might be empty. + * + * @param subdir Identify top-level skin subdirectory by passing one of + * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file + * lives under "textures" subtree), LLDir::SKINBASE (file lives at top + * level of skin subdirectory). + * @param filename Desired filename within subdir within skin, e.g. + * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language. + * @param constraint Callers perform two different kinds of processing. + * When fetching a XUI file, for instance, the existence of @a filename in + * the specified skin completely supercedes any @a filename in the default + * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The + * returned vector will contain only + * ".../current_skin/xui/en/filename", + * ".../current_skin/xui/current_language/filename". + * But for (e.g.) "strings.xml", we want a given skin to be able to + * override only specific entries from the default skin. Any string not + * defined in the specified skin will be sought in the default skin. For + * that case, pass @a constraint=ALL_SKINS. The returned vector will + * contain at least ".../default/xui/en/strings.xml", + * ".../default/xui/current_language/strings.xml", + * ".../current_skin/xui/en/strings.xml", + * ".../current_skin/xui/current_language/strings.xml". + */ + std::vector findSkinnedFilenames(const std::string& subdir, + const std::string& filename, + ESkinConstraint constraint=CURRENT_SKIN) const; + /// Values for findSkinnedFilenames(subdir) parameter + static const char *XUI, *TEXTURES, *SKINBASE; + /** + * Return the base-language pathname from findSkinnedFilenames(), or + * the empty string if no such file exists. Parameters are identical to + * findSkinnedFilenames(). This is shorthand for capturing the vector + * returned by findSkinnedFilenames(), checking for empty() and then + * returning front(). + */ + std::string findSkinnedFilenameBaseLang(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint=CURRENT_SKIN) const; + /** + * Return the "most localized" pathname from findSkinnedFilenames(), or + * the empty string if no such file exists. Parameters are identical to + * findSkinnedFilenames(). This is shorthand for capturing the vector + * returned by findSkinnedFilenames(), checking for empty() and then + * returning back(). + */ + std::string findSkinnedFilename(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint=CURRENT_SKIN) const; + + // random filename in common temporary directory + std::string getTempFilename() const; + + // For producing safe download file names from potentially unsafe ones + static std::string getScrubbedFileName(const std::string uncleanFileName); + static std::string getForbiddenFileChars(); + void setDumpDir( const std::string& path ); + + + virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir + virtual void setPerAccountChatLogsDir(const std::string &username); // Set the per user chat log directory. + virtual void setLindenUserDir(const std::string &username); // Set the linden user dir to this user's dir + virtual void setSkinFolder(const std::string &skin_folder, const std::string& language); + virtual std::string getSkinFolder() const; + virtual std::string getLanguage() const; + virtual bool setCacheDir(const std::string &path); + virtual void updatePerAccountChatLogsDir(); + + virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG); + + // Utility routine + std::string buildSLOSCacheDir() const; + + /// Append specified @a name to @a destpath, separated by getDirDelimiter() + /// if both are non-empty. + void append(std::string& destpath, const std::string& name) const; + /// Variadic form: append @a name0 and @a name1 and arbitrary other @a + /// names to @a destpath, separated by getDirDelimiter() as needed. + template + void append(std::string& destpath, const std::string& name0, const std::string& name1, + const NAMES& ... names) const + { + // In a typical recursion case, we'd accept (destpath, name0, names). + // We accept (destpath, name0, name1, names) because it's important to + // delegate the two-argument case to the non-template implementation. + append(destpath, name0); + append(destpath, name1, names...); + } + + /// Append specified @a names to @a path, separated by getDirDelimiter() + /// as needed. Return result, leaving @a path unmodified. + template + std::string add(const std::string& path, const NAMES& ... names) const + { + std::string destpath(path); + append(destpath, names...); + return destpath; + } + +protected: + // Does an add() or append() call need a directory delimiter? + typedef std::pair SepOff; + SepOff needSep(const std::string& path, const std::string& name) const; + // build mSearchSkinDirs without adding duplicates + void addSearchSkinDir(const std::string& skindir); + + // Internal to findSkinnedFilenames() + template + void walkSearchSkinDirs(const std::string& subdir, + const std::vector& subsubdirs, + const std::string& filename, + const FUNCTION& function) const; + + std::string mAppName; // install directory under progams/ ie "SecondLife" + std::string mExecutablePathAndName; // full path + Filename of .exe + std::string mExecutableFilename; // Filename of .exe + std::string mExecutableDir; // Location of executable + std::string mWorkingDir; // Current working directory + std::string mAppRODataDir; // Location for static app data + std::string mOSUserDir; // OS Specific user directory + std::string mOSUserAppDir; // OS Specific user app directory + std::string mLindenUserDir; // Location for Linden user-specific data + std::string mPerAccountChatLogsDir; // Location for chat logs. + std::string mChatLogsDir; // Location for chat logs. + std::string mCAFile; // Location of the TLS certificate authority PEM file. + std::string mTempDir; + std::string mCacheDir; // cache directory as set by user preference + std::string mDefaultCacheDir; // default cache diretory + std::string mOSCacheDir; // operating system cache dir + std::string mDirDelimiter; + std::string mSkinName; // caller-specified skin name + std::string mSkinBaseDir; // Base for skins paths. + std::string mDefaultSkinDir; // Location for default skin info. + std::string mSkinDir; // Location for current skin info. + std::string mUserDefaultSkinDir; // Location for default skin info. + std::string mUserSkinDir; // Location for user-modified skin info. + // Skin directories to search, most general to most specific. This order + // works well for composing fine-grained files, in which an individual item + // in a specific file overrides the corresponding item in more general + // files. Of course, for a file-level search, iterate backwards. + std::vector mSearchSkinDirs; + std::string mLanguage; // Current viewer language + std::string mLLPluginDir; // Location for plugins and plugin shell + static std::string sDumpDir; // Per-run crash report subdir of log directory. + std::string mUserName; // Current user name +}; + +void dir_exists_or_crash(const std::string &dir_name); + +extern LLDir *gDirUtilp; + +#endif // LL_LLDIR_H diff --git a/indra/llfilesystem/lldir_linux.cpp b/indra/llfilesystem/lldir_linux.cpp new file mode 100644 index 0000000000..80ad05345a --- /dev/null +++ b/indra/llfilesystem/lldir_linux.cpp @@ -0,0 +1,269 @@ +/** + * @file lldir_linux.cpp + * @brief Implementation of directory utilities for linux + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lldir_linux.h" +#include "llerror.h" +#include "llrand.h" +#include "llstring.h" +#include +#include +#include +#include +#include + + +static std::string getCurrentUserHome(char* fallback) +{ + const uid_t uid = getuid(); + struct passwd *pw; + + pw = getpwuid(uid); + if ((pw != NULL) && (pw->pw_dir != NULL)) + { + return pw->pw_dir; + } + + LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL; + auto home_env = LLStringUtil::getoptenv("HOME"); + if (home_env) + { + return *home_env; + } + else + { + LL_WARNS() << "Couldn't detect home directory! Falling back to " << fallback << LL_ENDL; + return fallback; + } +} + + +LLDir_Linux::LLDir_Linux() +{ + mDirDelimiter = "/"; + mCurrentDirIndex = -1; + mCurrentDirCount = -1; + mDirp = NULL; + + char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ + if (getcwd(tmp_str, LL_MAX_PATH) == NULL) + { + strcpy(tmp_str, "/tmp"); + LL_WARNS() << "Could not get current directory; changing to " + << tmp_str << LL_ENDL; + if (chdir(tmp_str) == -1) + { + LL_ERRS() << "Could not change directory to " << tmp_str << LL_ENDL; + } + } + + mExecutableFilename = ""; + mExecutablePathAndName = ""; + mExecutableDir = tmp_str; + mWorkingDir = tmp_str; +#ifdef APP_RO_DATA_DIR + mAppRODataDir = APP_RO_DATA_DIR; +#else + mAppRODataDir = tmp_str; +#endif + std::string::size_type build_dir_pos = mExecutableDir.rfind("/build-linux-"); + if (build_dir_pos != std::string::npos) + { + // ...we're in a dev checkout + mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "/indra/newview/skins"; + LL_INFOS() << "Running in dev checkout with mSkinBaseDir " + << mSkinBaseDir << LL_ENDL; + } + else + { + // ...normal installation running + mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; + } + + mOSUserDir = getCurrentUserHome(tmp_str); + mOSUserAppDir = ""; + mLindenUserDir = ""; + + char path [32]; /* Flawfinder: ignore */ + + // *NOTE: /proc/%d/exe doesn't work on FreeBSD. But that's ok, + // because this is the linux implementation. + + snprintf (path, sizeof(path), "/proc/%d/exe", (int) getpid ()); + int rc = readlink (path, tmp_str, sizeof (tmp_str)-1); /* Flawfinder: ignore */ + if ( (rc != -1) && (rc <= ((int) sizeof (tmp_str)-1)) ) + { + tmp_str[rc] = '\0'; //readlink() doesn't 0-terminate the buffer + mExecutablePathAndName = tmp_str; + char *path_end; + if ((path_end = strrchr(tmp_str,'/'))) + { + *path_end = '\0'; + mExecutableDir = tmp_str; + mWorkingDir = tmp_str; + mExecutableFilename = path_end+1; + } + else + { + mExecutableFilename = tmp_str; + } + } + + mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin"; + + // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. + mTempDir = "/tmp"; +} + +LLDir_Linux::~LLDir_Linux() +{ +} + +// Implementation + + +void LLDir_Linux::initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir) +{ + // Allow override so test apps can read newview directory + if (!app_read_only_data_dir.empty()) + { + mAppRODataDir = app_read_only_data_dir; + mSkinBaseDir = add(mAppRODataDir, "skins"); + } + mAppName = app_name; + + std::string upper_app_name(app_name); + LLStringUtil::toUpper(upper_app_name); + + auto app_home_env(LLStringUtil::getoptenv(upper_app_name + "_USER_DIR")); + if (app_home_env) + { + // user has specified own userappdir i.e. $SECONDLIFE_USER_DIR + mOSUserAppDir = *app_home_env; + } + else + { + // traditionally on unixoids, MyApp gets ~/.myapp dir for data + mOSUserAppDir = mOSUserDir; + mOSUserAppDir += "/"; + mOSUserAppDir += "."; + std::string lower_app_name(app_name); + LLStringUtil::toLower(lower_app_name); + mOSUserAppDir += lower_app_name; + } + + // create any directories we expect to write to. + + int res = LLFile::mkdir(mOSUserAppDir); + if (res == -1) + { + LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL; + LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL; + mOSUserAppDir = mOSUserDir; + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"")); + if (res == -1) + { + LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL; + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"")); + if (res == -1) + { + LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL; + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"")); + if (res == -1) + { + LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; + } + + mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "ca-bundle.crt"); +} + +U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string &mask) +{ + U32 file_count = 0; + glob_t g; + + std::string tmp_str; + tmp_str = dirname; + tmp_str += mask; + + if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) + { + file_count = g.gl_pathc; + + globfree(&g); + } + + return (file_count); +} + +std::string LLDir_Linux::getCurPath() +{ + char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ + if (getcwd(tmp_str, LL_MAX_PATH) == NULL) + { + LL_WARNS() << "Could not get current directory" << LL_ENDL; + tmp_str[0] = '\0'; + } + 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() + + "SLPlugin"; +} + +/*virtual*/ std::string LLDir_Linux::getLLPluginFilename(std::string base_name) +{ + return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + + "lib" + base_name + ".so"; +} diff --git a/indra/llfilesystem/lldir_linux.h b/indra/llfilesystem/lldir_linux.h new file mode 100644 index 0000000000..e83a020ba4 --- /dev/null +++ b/indra/llfilesystem/lldir_linux.h @@ -0,0 +1,64 @@ +/** + * @file lldir_linux.h + * @brief Definition of directory utilities class for linux + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if !LL_LINUX +#error This header must not be included when compiling for any target other than Linux. Consider including lldir.h instead. +#endif // !LL_LINUX + +#ifndef LL_LLDIR_LINUX_H +#define LL_LLDIR_LINUX_H + +#include "lldir.h" + +#include +#include + +class LLDir_Linux : public LLDir +{ +public: + LLDir_Linux(); + virtual ~LLDir_Linux(); + + /*virtual*/ void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir); + + 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); + +private: + DIR *mDirp; + int mCurrentDirIndex; + int mCurrentDirCount; + std::string mCurrentDir; +}; + +#endif // LL_LLDIR_LINUX_H + + diff --git a/indra/llfilesystem/lldir_mac.cpp b/indra/llfilesystem/lldir_mac.cpp new file mode 100644 index 0000000000..3bc4ee844e --- /dev/null +++ b/indra/llfilesystem/lldir_mac.cpp @@ -0,0 +1,205 @@ +/** + * @file lldir_mac.cpp + * @brief Implementation of directory utilities for Mac OS X + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if LL_DARWIN + +#include "linden_common.h" + +#include "lldir_mac.h" +#include "llerror.h" +#include "llrand.h" +#include +#include +#include +#include +#include +#include "lldir_utils_objc.h" + +// -------------------------------------------------------------------------------- + +static bool CreateDirectory(const std::string &parent, + const std::string &child, + std::string *fullname) +{ + + boost::filesystem::path p(parent); + p /= child; + + if (fullname) + *fullname = std::string(p.string()); + + if (! boost::filesystem::create_directory(p)) + { + return (boost::filesystem::is_directory(p)); + } + return true; +} + +// -------------------------------------------------------------------------------- + +LLDir_Mac::LLDir_Mac() +{ + mDirDelimiter = "/"; + + const std::string secondLifeString = "SecondLife"; + + std::string *executablepathstr = getSystemExecutableFolder(); + + //NOTE: LLINFOS/LLERRS will not output to log here. The streams are not initialized. + + if (executablepathstr) + { + // mExecutablePathAndName + mExecutablePathAndName = *executablepathstr; + + boost::filesystem::path executablepath(*executablepathstr); + +# ifndef BOOST_SYSTEM_NO_DEPRECATED +#endif + mExecutableFilename = executablepath.filename().string(); + mExecutableDir = executablepath.parent_path().string(); + + // mAppRODataDir + std::string *resourcepath = getSystemResourceFolder(); + mAppRODataDir = *resourcepath; + + // *NOTE: When running in a dev tree, use the copy of + // skins in indra/newview/ rather than in the application bundle. This + // mirrors Windows dev environment behavior and allows direct checkin + // of edited skins/xui files. JC + + // MBW -- This keeps the mac application from finding other things. + // If this is really for skins, it should JUST apply to skins. + + std::string::size_type build_dir_pos = mExecutableDir.rfind("/build-darwin-"); + if (build_dir_pos != std::string::npos) + { + // ...we're in a dev checkout + mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + + "/indra/newview/skins"; + LL_INFOS() << "Running in dev checkout with mSkinBaseDir " + << mSkinBaseDir << LL_ENDL; + } + else + { + // ...normal installation running + mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; + } + + // mOSUserDir + std::string *appdir = getSystemApplicationSupportFolder(); + std::string rootdir; + + //Create root directory + if (CreateDirectory(*appdir, secondLifeString, &rootdir)) + { + + // Save the full path to the folder + mOSUserDir = rootdir; + + // Create our sub-dirs + CreateDirectory(rootdir, std::string("data"), NULL); + CreateDirectory(rootdir, std::string("logs"), NULL); + CreateDirectory(rootdir, std::string("user_settings"), NULL); + CreateDirectory(rootdir, std::string("browser_profile"), NULL); + } + + //mOSCacheDir + std::string *cachedir = getSystemCacheFolder(); + + if (cachedir) + + { + mOSCacheDir = *cachedir; + //TODO: This changes from ~/Library/Cache/Secondlife to ~/Library/Cache/com.app.secondlife/Secondlife. Last dir level could go away. + CreateDirectory(mOSCacheDir, secondLifeString, NULL); + } + + // mOSUserAppDir + mOSUserAppDir = mOSUserDir; + + // mTempDir + //Aura 120920 boost::filesystem::temp_directory_path() not yet implemented on mac. :( + std::string *tmpdir = getSystemTempFolder(); + if (tmpdir) + { + + CreateDirectory(*tmpdir, secondLifeString, &mTempDir); + if (tmpdir) delete tmpdir; + } + + mWorkingDir = getCurPath(); + + mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin"; + } +} + +LLDir_Mac::~LLDir_Mac() +{ +} + +// Implementation + + +void LLDir_Mac::initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir) +{ + // Allow override so test apps can read newview directory + if (!app_read_only_data_dir.empty()) + { + mAppRODataDir = app_read_only_data_dir; + mSkinBaseDir = add(mAppRODataDir, "skins"); + } + mCAFile = add(mAppRODataDir, "ca-bundle.crt"); +} + +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() + + "SLPlugin.app/Contents/MacOS/SLPlugin"; +} + +/*virtual*/ std::string LLDir_Mac::getLLPluginFilename(std::string base_name) +{ + return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + + base_name + ".dylib"; +} + + +#endif // LL_DARWIN diff --git a/indra/llfilesystem/lldir_mac.h b/indra/llfilesystem/lldir_mac.h new file mode 100644 index 0000000000..558727ebbc --- /dev/null +++ b/indra/llfilesystem/lldir_mac.h @@ -0,0 +1,56 @@ +/** + * @file lldir_mac.h + * @brief Definition of directory utilities class for Mac OS X + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if !LL_DARWIN +#error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead. +#endif // !LL_DARWIN + +#ifndef LL_LLDIR_MAC_H +#define LL_LLDIR_MAC_H + +#include "lldir.h" + +#include + +class LLDir_Mac : public LLDir +{ +public: + LLDir_Mac(); + virtual ~LLDir_Mac(); + + /*virtual*/ void initAppDirs(const std::string &app_name, + 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); +}; + +#endif // LL_LLDIR_MAC_H + + diff --git a/indra/llfilesystem/lldir_solaris.cpp b/indra/llfilesystem/lldir_solaris.cpp new file mode 100644 index 0000000000..f18560ff20 --- /dev/null +++ b/indra/llfilesystem/lldir_solaris.cpp @@ -0,0 +1,266 @@ +/** + * @file fmodwrapper.cpp + * @brief dummy source file for building a shared library to wrap libfmod.a + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lldir_solaris.h" +#include "llerror.h" +#include "llrand.h" +#include "llstring.h" +#include +#include +#include +#include +#include +#include +#define _STRUCTURED_PROC 1 +#include +#include + +static std::string getCurrentUserHome(char* fallback) +{ + // fwiw this exactly duplicates getCurrentUserHome() in lldir_linux.cpp... + // we should either derive both from LLDir_Posix or just axe Solaris. + const uid_t uid = getuid(); + struct passwd *pw; + + pw = getpwuid(uid); + if ((pw != NULL) && (pw->pw_dir != NULL)) + { + return pw->pw_dir; + } + + LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL; + auto home_env = LLStringUtil::getoptenv("HOME"); + if (home_env) + { + return *home_env; + } + else + { + LL_WARNS() << "Couldn't detect home directory! Falling back to " << fallback << LL_ENDL; + return fallback; + } +} + + +LLDir_Solaris::LLDir_Solaris() +{ + mDirDelimiter = "/"; + mCurrentDirIndex = -1; + mCurrentDirCount = -1; + mDirp = NULL; + + char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ + if (getcwd(tmp_str, LL_MAX_PATH) == NULL) + { + strcpy(tmp_str, "/tmp"); + LL_WARNS() << "Could not get current directory; changing to " + << tmp_str << LL_ENDL; + if (chdir(tmp_str) == -1) + { + LL_ERRS() << "Could not change directory to " << tmp_str << LL_ENDL; + } + } + + mExecutableFilename = ""; + mExecutablePathAndName = ""; + mExecutableDir = strdup(tmp_str); + mWorkingDir = strdup(tmp_str); + mAppRODataDir = strdup(tmp_str); + mOSUserDir = getCurrentUserHome(tmp_str); + mOSUserAppDir = ""; + mLindenUserDir = ""; + + char path [LL_MAX_PATH]; /* Flawfinder: ignore */ + + sprintf(path, "/proc/%d/psinfo", (int)getpid()); + int proc_fd = -1; + if((proc_fd = open(path, O_RDONLY)) == -1){ + LL_WARNS() << "unable to open " << path << LL_ENDL; + return; + } + psinfo_t proc_psinfo; + if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){ + LL_WARNS() << "Unable to read " << path << LL_ENDL; + close(proc_fd); + return; + } + + close(proc_fd); + + mExecutableFilename = strdup(proc_psinfo.pr_fname); + LL_INFOS() << "mExecutableFilename = [" << mExecutableFilename << "]" << LL_ENDL; + + sprintf(path, "/proc/%d/path/a.out", (int)getpid()); + + char execpath[LL_MAX_PATH]; + if(readlink(path, execpath, LL_MAX_PATH) == -1){ + LL_WARNS() << "Unable to read link from " << path << LL_ENDL; + return; + } + + char *p = execpath; // nuke trash in link, if any exists + int i = 0; + while(*p != NULL && ++i < LL_MAX_PATH && isprint((int)(*p++))); + *p = NULL; + + mExecutablePathAndName = strdup(execpath); + LL_INFOS() << "mExecutablePathAndName = [" << mExecutablePathAndName << "]" << LL_ENDL; + + //NOTE: Why force people to cd into the package directory? + // Look for SECONDLIFE env variable and use it, if set. + + auto SECONDLIFE(LLDirUtil::getoptenv("SECONDLIFE")); + if(SECONDLIFE){ + mExecutableDir = add(*SECONDLIFE, "bin"); //NOTE: make sure we point at the bin + }else{ + mExecutableDir = getDirName(execpath); + LL_INFOS() << "mExecutableDir = [" << mExecutableDir << "]" << LL_ENDL; + } + + mLLPluginDir = add(mExecutableDir, "llplugin"); + + // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. + mTempDir = "/tmp"; +} + +LLDir_Solaris::~LLDir_Solaris() +{ +} + +// Implementation + + +void LLDir_Solaris::initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir) +{ + // Allow override so test apps can read newview directory + if (!app_read_only_data_dir.empty()) + { + mAppRODataDir = app_read_only_data_dir; + mSkinBaseDir = add(mAppRODataDir, "skins"); + } + mAppName = app_name; + + std::string upper_app_name(app_name); + LLStringUtil::toUpper(upper_app_name); + + auto app_home_env(LLStringUtil::getoptenv(upper_app_name + "_USER_DIR")); + if (app_home_env) + { + // user has specified own userappdir i.e. $SECONDLIFE_USER_DIR + mOSUserAppDir = *app_home_env; + } + else + { + // traditionally on unixoids, MyApp gets ~/.myapp dir for data + mOSUserAppDir = mOSUserDir; + mOSUserAppDir += "/"; + mOSUserAppDir += "."; + std::string lower_app_name(app_name); + LLStringUtil::toLower(lower_app_name); + mOSUserAppDir += lower_app_name; + } + + // create any directories we expect to write to. + + int res = LLFile::mkdir(mOSUserAppDir); + if (res == -1) + { + LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL; + LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL; + mOSUserAppDir = mOSUserDir; + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"")); + if (res == -1) + { + LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL; + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"")); + if (res == -1) + { + LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL; + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"")); + if (res == -1) + { + LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; + } + + mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "ca-bundle.crt"); +} + +U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string &mask) +{ + U32 file_count = 0; + glob_t g; + + std::string tmp_str; + tmp_str = dirname; + tmp_str += mask; + + if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) + { + file_count = g.gl_pathc; + + globfree(&g); + } + + return (file_count); +} + +std::string LLDir_Solaris::getCurPath() +{ + char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ + if (getcwd(tmp_str, LL_MAX_PATH) == NULL) + { + LL_WARNS() << "Could not get current directory" << LL_ENDL; + tmp_str[0] = '\0'; + } + return tmp_str; +} + + +bool LLDir_Solaris::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; + } +} + diff --git a/indra/llfilesystem/lldir_solaris.h b/indra/llfilesystem/lldir_solaris.h new file mode 100644 index 0000000000..c6dac57e14 --- /dev/null +++ b/indra/llfilesystem/lldir_solaris.h @@ -0,0 +1,61 @@ +/** + * @file fmodwrapper.cpp + * @brief dummy source file for building a shared library to wrap libfmod.a + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if !LL_SOLARIS +#error This header must not be included when compiling for any target other than Solaris. Consider including lldir.h instead. +#endif // !LL_SOLARIS + +#ifndef LL_LLDIR_SOLARIS_H +#define LL_LLDIR_SOLARIS_H + +#include "lldir.h" + +#include +#include + +class LLDir_Solaris : public LLDir +{ +public: + LLDir_Solaris(); + virtual ~LLDir_Solaris(); + + /*virtual*/ void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir); + + virtual std::string getCurPath(); + virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); + /*virtual*/ bool fileExists(const std::string &filename) const; + +private: + DIR *mDirp; + int mCurrentDirIndex; + int mCurrentDirCount; + std::string mCurrentDir; +}; + +#endif // LL_LLDIR_SOLARIS_H + + diff --git a/indra/llfilesystem/lldir_utils_objc.h b/indra/llfilesystem/lldir_utils_objc.h new file mode 100644 index 0000000000..12019c4284 --- /dev/null +++ b/indra/llfilesystem/lldir_utils_objc.h @@ -0,0 +1,43 @@ +/** + * @file lldir_utils_objc.h + * @brief Definition of directory utilities class for Mac OS X + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if !LL_DARWIN +#error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead. +#endif // !LL_DARWIN + +#ifndef LL_LLDIR_UTILS_OBJC_H +#define LL_LLDIR_UTILS_OBJC_H + +#include + +std::string* getSystemTempFolder(); +std::string* getSystemCacheFolder(); +std::string* getSystemApplicationSupportFolder(); +std::string* getSystemResourceFolder(); +std::string* getSystemExecutableFolder(); + + +#endif // LL_LLDIR_UTILS_OBJC_H diff --git a/indra/llfilesystem/lldir_utils_objc.mm b/indra/llfilesystem/lldir_utils_objc.mm new file mode 100644 index 0000000000..da55a2f897 --- /dev/null +++ b/indra/llfilesystem/lldir_utils_objc.mm @@ -0,0 +1,108 @@ +/** + * @file lldir_utils_objc.mm + * @brief Cocoa implementation of directory utilities for Mac OS X + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#if LL_DARWIN + +//WARNING: This file CANNOT use standard linden includes due to conflicts between definitions of BOOL + +#include "lldir_utils_objc.h" +#import + +std::string* getSystemTempFolder() +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString * tempDir = NSTemporaryDirectory(); + if (tempDir == nil) + tempDir = @"/tmp"; + std::string *result = ( new std::string([tempDir UTF8String]) ); + [pool release]; + + return result; +} + +//findSystemDirectory scoped exclusively to this file. +std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory, + NSSearchPathDomainMask domainMask) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + std::string *result = nil; + NSString *path = nil; + + // Search for the path + NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory, + domainMask, + YES); + if ([paths count]) + { + path = [paths objectAtIndex:0]; + //HACK: Always attempt to create directory, ignore errors. + NSError *error = nil; + + [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error]; + + + result = new std::string([path UTF8String]); + } + [pool release]; + return result; +} + +std::string* getSystemExecutableFolder() +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSString *bundlePath = [[NSBundle mainBundle] executablePath]; + std::string *result = (new std::string([bundlePath UTF8String])); + [pool release]; + + return result; +} + +std::string* getSystemResourceFolder() +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSString *bundlePath = [[NSBundle mainBundle] resourcePath]; + std::string *result = (new std::string([bundlePath UTF8String])); + [pool release]; + + return result; +} + +std::string* getSystemCacheFolder() +{ + return findSystemDirectory (NSCachesDirectory, + NSUserDomainMask); +} + +std::string* getSystemApplicationSupportFolder() +{ + return findSystemDirectory (NSApplicationSupportDirectory, + NSUserDomainMask); + +} + +#endif // LL_DARWIN diff --git a/indra/llfilesystem/lldir_win32.cpp b/indra/llfilesystem/lldir_win32.cpp new file mode 100644 index 0000000000..b3b3afb37e --- /dev/null +++ b/indra/llfilesystem/lldir_win32.cpp @@ -0,0 +1,452 @@ +/** + * @file lldir_win32.cpp + * @brief Implementation of directory utilities for windows + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if LL_WINDOWS + +#include "linden_common.h" + +#include "lldir_win32.h" +#include "llerror.h" +#include "llstring.h" +#include "stringize.h" +#include "llfile.h" +#include +#include + +#include +#include +#include +#include + +// Utility stuff to get versions of the sh +#define PACKVERSION(major,minor) MAKELONG(minor,major) +DWORD GetDllVersion(LPCTSTR lpszDllName); + +namespace +{ // anonymous + enum class prst { INIT, OPEN, SKIP } state = prst::INIT; + // This is called so early that we can't count on static objects being + // properly constructed yet, so declare a pointer instead of an instance. + std::ofstream* prelogf = nullptr; + + void prelog(const std::string& message) + { + boost::optional prelog_name; + + switch (state) + { + case prst::INIT: + // assume we failed, until we succeed + state = prst::SKIP; + + prelog_name = LLStringUtil::getoptenv("PRELOG"); + if (! prelog_name) + // no PRELOG variable set, carry on + return; + prelogf = new llofstream(*prelog_name, std::ios_base::app); + if (! (prelogf && prelogf->is_open())) + // can't complain to anybody; how? + return; + // got the log file open, cool! + state = prst::OPEN; + (*prelogf) << "========================================================================" + << std::endl; + // fall through, don't break + + case prst::OPEN: + (*prelogf) << message << std::endl; + break; + + case prst::SKIP: + // either PRELOG isn't set, or we failed to open that pathname + break; + } + } +} // anonymous namespace + +#define PRELOG(expression) prelog(STRINGIZE(expression)) + +LLDir_Win32::LLDir_Win32() +{ + // set this first: used by append() and add() methods + mDirDelimiter = "\\"; + + WCHAR w_str[MAX_PATH]; + // Application Data is where user settings go. We rely on $APPDATA being + // correct. + auto APPDATA = LLStringUtil::getoptenv("APPDATA"); + if (APPDATA) + { + mOSUserDir = *APPDATA; + } + PRELOG("APPDATA='" << mOSUserDir << "'"); + // On Windows, we could have received a plain-ASCII pathname in which + // non-ASCII characters have been munged to '?', or the pathname could + // have been badly encoded and decoded such that we now have garbage + // instead of a valid path. Check that mOSUserDir actually exists. + if (mOSUserDir.empty() || ! fileExists(mOSUserDir)) + { + PRELOG("APPDATA does not exist"); + //HRESULT okay = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, w_str); + wchar_t *pwstr = NULL; + HRESULT okay = SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &pwstr); + PRELOG("SHGetKnownFolderPath(FOLDERID_RoamingAppData) returned " << okay); + if (SUCCEEDED(okay) && pwstr) + { + // But of course, only update mOSUserDir if SHGetKnownFolderPath() works. + mOSUserDir = ll_convert_wide_to_string(pwstr); + // Not only that: update our environment so that child processes + // will see a reasonable value as well. + _wputenv_s(L"APPDATA", pwstr); + // SHGetKnownFolderPath() contract requires us to free pwstr + CoTaskMemFree(pwstr); + PRELOG("mOSUserDir='" << mOSUserDir << "'"); + } + } + + // We want cache files to go on the local disk, even if the + // user is on a network with a "roaming profile". + // + // On Vista this is: + // C:\Users\James\AppData\Local + // + // We used to store the cache in AppData\Roaming, and the installer + // cleans up that version on upgrade. JC + auto LOCALAPPDATA = LLStringUtil::getoptenv("LOCALAPPDATA"); + if (LOCALAPPDATA) + { + mOSCacheDir = *LOCALAPPDATA; + } + PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'"); + // Windows really does not deal well with pathnames containing non-ASCII + // characters. See above remarks about APPDATA. + if (mOSCacheDir.empty() || ! fileExists(mOSCacheDir)) + { + PRELOG("LOCALAPPDATA does not exist"); + //HRESULT okay = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, w_str); + wchar_t *pwstr = NULL; + HRESULT okay = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pwstr); + PRELOG("SHGetKnownFolderPath(FOLDERID_LocalAppData) returned " << okay); + if (SUCCEEDED(okay) && pwstr) + { + // But of course, only update mOSCacheDir if SHGetKnownFolderPath() works. + mOSCacheDir = ll_convert_wide_to_string(pwstr); + // Update our environment so that child processes will see a + // reasonable value as well. + _wputenv_s(L"LOCALAPPDATA", pwstr); + // SHGetKnownFolderPath() contract requires us to free pwstr + CoTaskMemFree(pwstr); + PRELOG("mOSCacheDir='" << mOSCacheDir << "'"); + } + } + + if (GetTempPath(MAX_PATH, w_str)) + { + if (wcslen(w_str)) /* Flawfinder: ignore */ + { + w_str[wcslen(w_str)-1] = '\0'; /* Flawfinder: ignore */ // remove trailing slash + } + mTempDir = utf16str_to_utf8str(llutf16string(w_str)); + + if (mOSUserDir.empty()) + { + mOSUserDir = mTempDir; + } + + if (mOSCacheDir.empty()) + { + mOSCacheDir = mTempDir; + } + } + else + { + mTempDir = mOSUserDir; + } + +/*==========================================================================*| + // Now that we've got mOSUserDir, one way or another, let's see how we did + // with our environment variables. + { + auto report = [this](std::ostream& out){ + out << "mOSUserDir = '" << mOSUserDir << "'\n" + << "mOSCacheDir = '" << mOSCacheDir << "'\n" + << "mTempDir = '" << mTempDir << "'" << std::endl; + }; + int res = LLFile::mkdir(mOSUserDir); + if (res == -1) + { + // If we couldn't even create the directory, just blurt to stderr + report(std::cerr); + } + else + { + // successfully created logdir, plunk a log file there + std::string logfilename(add(mOSUserDir, "lldir.log")); + std::ofstream logfile(logfilename.c_str()); + if (! logfile.is_open()) + { + report(std::cerr); + } + else + { + report(logfile); + } + } + } +|*==========================================================================*/ + +// fprintf(stderr, "mTempDir = <%s>",mTempDir); + + // Set working directory, for LLDir::getWorkingDir() + GetCurrentDirectory(MAX_PATH, w_str); + mWorkingDir = utf16str_to_utf8str(llutf16string(w_str)); + + // Set the executable directory + S32 size = GetModuleFileName(NULL, w_str, MAX_PATH); + if (size) + { + w_str[size] = '\0'; + mExecutablePathAndName = utf16str_to_utf8str(llutf16string(w_str)); + S32 path_end = mExecutablePathAndName.find_last_of('\\'); + if (path_end != std::string::npos) + { + mExecutableDir = mExecutablePathAndName.substr(0, path_end); + mExecutableFilename = mExecutablePathAndName.substr(path_end+1, std::string::npos); + } + else + { + mExecutableFilename = mExecutablePathAndName; + } + + } + else + { + fprintf(stderr, "Couldn't get APP path, assuming current directory!"); + mExecutableDir = mWorkingDir; + // Assume it's the current directory + } + + // mAppRODataDir = "."; + + // Determine the location of the App-Read-Only-Data + // Try the working directory then the exe's dir. + mAppRODataDir = mWorkingDir; + + +// if (mExecutableDir.find("indra") == std::string::npos) + + // *NOTE:Mani - It is a mistake to put viewer specific code in + // the LLDir implementation. The references to 'skins' and + // 'llplugin' need to go somewhere else. + // alas... this also gets called during static initialization + // time due to the construction of gDirUtil in lldir.cpp. + if(! LLFile::isdir(add(mAppRODataDir, "skins"))) + { + // What? No skins in the working dir? + // Try the executable's directory. + mAppRODataDir = mExecutableDir; + } + +// LL_INFOS() << "mAppRODataDir = " << mAppRODataDir << LL_ENDL; + + mSkinBaseDir = add(mAppRODataDir, "skins"); + + // Build the default cache directory + mDefaultCacheDir = buildSLOSCacheDir(); + + // Make sure it exists + int res = LLFile::mkdir(mDefaultCacheDir); + if (res == -1) + { + LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << mDefaultCacheDir << LL_ENDL; + } + + mLLPluginDir = add(mExecutableDir, "llplugin"); +} + +LLDir_Win32::~LLDir_Win32() +{ +} + +// Implementation + +void LLDir_Win32::initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir) +{ + // Allow override so test apps can read newview directory + if (!app_read_only_data_dir.empty()) + { + mAppRODataDir = app_read_only_data_dir; + mSkinBaseDir = add(mAppRODataDir, "skins"); + } + mAppName = app_name; + mOSUserAppDir = add(mOSUserDir, app_name); + + int res = LLFile::mkdir(mOSUserAppDir); + if (res == -1) + { + LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL; + LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL; + mOSUserAppDir = mOSUserDir; + } + //dumpCurrentDirectories(); + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"")); + if (res == -1) + { + LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL; + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"")); + if (res == -1) + { + LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL; + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"")); + if (res == -1) + { + LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; + } + + mCAFile = getExpandedFilename( LL_PATH_EXECUTABLE, "ca-bundle.crt" ); +} + +U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &mask) +{ + HANDLE count_search_h; + U32 file_count; + + file_count = 0; + + WIN32_FIND_DATA FileData; + + llutf16string pathname = utf8str_to_utf16str(dirname); + pathname += utf8str_to_utf16str(mask); + + if ((count_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE) + { + file_count++; + + while (FindNextFile(count_search_h, &FileData)) + { + file_count++; + } + + FindClose(count_search_h); + } + + return (file_count); +} + +std::string LLDir_Win32::getCurPath() +{ + WCHAR w_str[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, w_str); + + return utf16str_to_utf8str(llutf16string(w_str)); +} + + +bool LLDir_Win32::fileExists(const std::string &filename) const +{ + llstat stat_data; + // Check the age of the file + // Now, we see if the files we've gathered are recent... + int res = LLFile::stat(filename, &stat_data); + if (!res) + { + return TRUE; + } + else + { + return FALSE; + } +} + + +/*virtual*/ std::string LLDir_Win32::getLLPluginLauncher() +{ + return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + + "SLPlugin.exe"; +} + +/*virtual*/ std::string LLDir_Win32::getLLPluginFilename(std::string base_name) +{ + return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + + base_name + ".dll"; +} + + +#if 0 +// Utility function to get version number of a DLL + +#define PACKVERSION(major,minor) MAKELONG(minor,major) + +DWORD GetDllVersion(LPCTSTR lpszDllName) +{ + + HINSTANCE hinstDll; + DWORD dwVersion = 0; + + hinstDll = LoadLibrary(lpszDllName); /* Flawfinder: ignore */ + + if(hinstDll) + { + DLLGETVERSIONPROC pDllGetVersion; + + pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion"); + +/*Because some DLLs might not implement this function, you + must test for it explicitly. Depending on the particular + DLL, the lack of a DllGetVersion function can be a useful + indicator of the version. +*/ + if(pDllGetVersion) + { + DLLVERSIONINFO dvi; + HRESULT hr; + + ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + + hr = (*pDllGetVersion)(&dvi); + + if(SUCCEEDED(hr)) + { + dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion); + } + } + + FreeLibrary(hinstDll); + } + return dwVersion; +} +#endif + +#endif + + diff --git a/indra/llfilesystem/lldir_win32.h b/indra/llfilesystem/lldir_win32.h new file mode 100644 index 0000000000..450efaf9da --- /dev/null +++ b/indra/llfilesystem/lldir_win32.h @@ -0,0 +1,59 @@ +/** + * @file lldir_win32.h + * @brief Definition of directory utilities class for windows + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if !LL_WINDOWS +#error This header must not be included when compiling for any target other than Windows. Consider including lldir.h instead. +#endif // !LL_WINDOWS + +#ifndef LL_LLDIR_WIN32_H +#define LL_LLDIR_WIN32_H + +#include "lldir.h" + +class LLDir_Win32 : public LLDir +{ +public: + LLDir_Win32(); + virtual ~LLDir_Win32(); + + /*virtual*/ void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir); + + /*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); + +private: + void* mDirSearch_h; + llutf16string mCurrentDir; +}; + +#endif // LL_LLDIR_WIN32_H + + diff --git a/indra/llfilesystem/lldirguard.h b/indra/llfilesystem/lldirguard.h new file mode 100644 index 0000000000..37b9e9b83e --- /dev/null +++ b/indra/llfilesystem/lldirguard.h @@ -0,0 +1,72 @@ +/** + * @file lldirguard.h + * @brief Protect working directory from being changed in scope. + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_DIRGUARD_H +#define LL_DIRGUARD_H + +#include "linden_common.h" +#include "llerror.h" + +#if LL_WINDOWS +class LLDirectoryGuard +{ +public: + LLDirectoryGuard() + { + mOrigDirLen = GetCurrentDirectory(MAX_PATH, mOrigDir); + } + + ~LLDirectoryGuard() + { + mFinalDirLen = GetCurrentDirectory(MAX_PATH, mFinalDir); + if ((mOrigDirLen!=mFinalDirLen) || + (wcsncmp(mOrigDir,mFinalDir,mOrigDirLen)!=0)) + { + // Dir has changed + std::string mOrigDirUtf8 = utf16str_to_utf8str(llutf16string(mOrigDir)); + std::string mFinalDirUtf8 = utf16str_to_utf8str(llutf16string(mFinalDir)); + LL_INFOS() << "Resetting working dir from " << mFinalDirUtf8 << " to " << mOrigDirUtf8 << LL_ENDL; + SetCurrentDirectory(mOrigDir); + } + } + +private: + TCHAR mOrigDir[MAX_PATH]; + DWORD mOrigDirLen; + TCHAR mFinalDir[MAX_PATH]; + DWORD mFinalDirLen; +}; +#else // No-op outside Windows. +class LLDirectoryGuard +{ +public: + LLDirectoryGuard() {} + ~LLDirectoryGuard() {} +}; +#endif + + +#endif diff --git a/indra/llfilesystem/lldiriterator.cpp b/indra/llfilesystem/lldiriterator.cpp new file mode 100644 index 0000000000..3eb64e69d9 --- /dev/null +++ b/indra/llfilesystem/lldiriterator.cpp @@ -0,0 +1,243 @@ +/** + * @file lldiriterator.cpp + * @brief Iterator through directory entries matching the search pattern. + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "lldiriterator.h" + +#include "fix_macros.h" +#include +#include + +namespace fs = boost::filesystem; + +static std::string glob_to_regex(const std::string& glob); + +class LLDirIterator::Impl +{ +public: + Impl(const std::string &dirname, const std::string &mask); + ~Impl(); + + bool next(std::string &fname); + +private: + boost::regex mFilterExp; + fs::directory_iterator mIter; + bool mIsValid; +}; + +LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) + : mIsValid(false) +{ +#ifdef LL_WINDOWS // or BOOST_WINDOWS_API + fs::path dir_path(utf8str_to_utf16str(dirname)); +#else + fs::path dir_path(dirname); +#endif + + bool is_dir = false; + + // Check if path is a directory. + try + { + is_dir = fs::is_directory(dir_path); + } + catch (const fs::filesystem_error& e) + { + LL_WARNS() << e.what() << LL_ENDL; + return; + } + + if (!is_dir) + { + LL_WARNS() << "Invalid path: \"" << dir_path.string() << "\"" << LL_ENDL; + return; + } + + // Initialize the directory iterator for the given path. + try + { + mIter = fs::directory_iterator(dir_path); + } + catch (const fs::filesystem_error& e) + { + LL_WARNS() << e.what() << LL_ENDL; + return; + } + + // Convert the glob mask to a regular expression + std::string exp = glob_to_regex(mask); + + // Initialize boost::regex with the expression converted from + // the glob mask. + // An exception is thrown if the expression is not valid. + try + { + mFilterExp.assign(exp); + } + catch (boost::regex_error& e) + { + LL_WARNS() << "\"" << exp << "\" is not a valid regular expression: " + << e.what() << LL_ENDL; + return; + } + + mIsValid = true; +} + +LLDirIterator::Impl::~Impl() +{ +} + +bool LLDirIterator::Impl::next(std::string &fname) +{ + fname = ""; + + if (!mIsValid) + { + LL_WARNS() << "The iterator is not correctly initialized." << LL_ENDL; + return false; + } + + fs::directory_iterator end_itr; // default construction yields past-the-end + bool found = false; + + // Check if path is a directory. + try + { + while (mIter != end_itr && !found) + { + boost::smatch match; + std::string name = mIter->path().filename().string(); + found = boost::regex_match(name, match, mFilterExp); + if (found) + { + fname = name; + } + + ++mIter; + } + } + catch (const fs::filesystem_error& e) + { + LL_WARNS() << e.what() << LL_ENDL; + } + + return found; +} + +/** +Converts the incoming glob into a regex. This involves +converting incoming glob expressions to regex equivilents and +at the same time, escaping any regex meaningful characters which +do not have glob meaning, i.e. + .()+|^$ +in the input. +*/ +std::string glob_to_regex(const std::string& glob) +{ + std::string regex; + regex.reserve(glob.size()<<1); + S32 braces = 0; + bool escaped = false; + bool square_brace_open = false; + + for (std::string::const_iterator i = glob.begin(); i != glob.end(); ++i) + { + char c = *i; + + switch (c) + { + case '*': + if (glob.begin() == i) + { + regex+="[^.].*"; + } + else + { + regex+= escaped ? "*" : ".*"; + } + break; + case '?': + regex+= escaped ? '?' : '.'; + break; + case '{': + braces++; + regex+='('; + break; + case '}': + if (!braces) + { + LL_ERRS() << "glob_to_regex: Closing brace without an equivalent opening brace: " << glob << LL_ENDL; + } + + regex+=')'; + braces--; + break; + case ',': + regex+= braces ? '|' : c; + break; + case '!': + regex+= square_brace_open ? '^' : c; + break; + case '.': // This collection have different regex meaning + case '^': // and so need escaping. + case '(': + case ')': + case '+': + case '|': + case '$': + regex += '\\'; + default: + regex += c; + break; + } + + escaped = ('\\' == c); + square_brace_open = ('[' == c); + } + + if (braces) + { + LL_ERRS() << "glob_to_regex: Unterminated brace expression: " << glob << LL_ENDL; + } + + return regex; +} + +LLDirIterator::LLDirIterator(const std::string &dirname, const std::string &mask) +{ + mImpl = new Impl(dirname, mask); +} + +LLDirIterator::~LLDirIterator() +{ + delete mImpl; +} + +bool LLDirIterator::next(std::string &fname) +{ + return mImpl->next(fname); +} diff --git a/indra/llfilesystem/lldiriterator.h b/indra/llfilesystem/lldiriterator.h new file mode 100644 index 0000000000..0b48be41b3 --- /dev/null +++ b/indra/llfilesystem/lldiriterator.h @@ -0,0 +1,87 @@ +/** + * @file lldiriterator.h + * @brief Iterator through directory entries matching the search pattern. + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDIRITERATOR_H +#define LL_LLDIRITERATOR_H + +#include "linden_common.h" + +/** + * Class LLDirIterator + * + * Iterates through directory entries matching the search pattern. + */ +class LLDirIterator +{ +public: + /** + * Constructs LLDirIterator object to search for glob pattern + * matches in a directory. + * + * @param dirname - name of a directory to search in. + * @param mask - search pattern, a glob expression + * + * Wildcards supported in glob expressions: + * -------------------------------------------------------------- + * | Wildcard | Matches | + * -------------------------------------------------------------- + * | * |zero or more characters | + * | ? |exactly one character | + * | [abcde] |exactly one character listed | + * | [a-e] |exactly one character in the given range | + * | [!abcde] |any character that is not listed | + * | [!a-e] |any character that is not in the given range | + * | {abc,xyz} |exactly one entire word in the options given | + * -------------------------------------------------------------- + */ + LLDirIterator(const std::string &dirname, const std::string &mask); + + ~LLDirIterator(); + + /** + * Searches for the next directory entry matching the glob mask + * specified upon iterator construction. + * Returns true if a match is found, sets fname + * parameter to the name of the matched directory entry and + * increments the iterator position. + * + * Typical usage: + * + * LLDirIterator iter(directory, pattern); + * if ( iter.next(scanResult) ) + * + * + * @param fname - name of the matched directory entry. + * @return true if a match is found, false otherwise. + */ + bool next(std::string &fname); + +protected: + class Impl; + Impl* mImpl; +}; + +#endif //LL_LLDIRITERATOR_H diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp new file mode 100644 index 0000000000..af93049e07 --- /dev/null +++ b/indra/llfilesystem/lldiskcache.cpp @@ -0,0 +1,387 @@ +/** + * @file lldiskcache.cpp + * @brief Implementation of virtual file + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lldiskcache.h" + +#include "llerror.h" +#include "llthread.h" +#include "lltimer.h" +#include "llfasttimer.h" +#include "llmemory.h" + +#include +#include "lldir.h" + +const S32 LLDiskCache::READ = 0x00000001; +const S32 LLDiskCache::WRITE = 0x00000002; +const S32 LLDiskCache::READ_WRITE = 0x00000003; // LLDiskCache::READ & LLDiskCache::WRITE +const S32 LLDiskCache::APPEND = 0x00000006; // 0x00000004 & LLDiskCache::WRITE + +static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait"); + +LLDiskCache::LLDiskCache(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode) +{ + mFileType = file_type; + mFileID = file_id; + mPosition = 0; + mBytesRead = 0; + mReadComplete = FALSE; + mMode = mode; +} + +LLDiskCache::~LLDiskCache() +{ +} + +const std::string assetTypeToString(LLAssetType::EType at) +{ + /** + * Make use of the C++17 (or is it 14) feature that allows + * for inline initialization of an std::map<> + */ + typedef std::map asset_type_to_name_t; + asset_type_to_name_t asset_type_to_name = + { + { LLAssetType::AT_TEXTURE, "TEXTURE" }, + { LLAssetType::AT_SOUND, "SOUND" }, + { LLAssetType::AT_CALLINGCARD, "CALLINGCARD" }, + { LLAssetType::AT_LANDMARK, "LANDMARK" }, + { LLAssetType::AT_SCRIPT, "SCRIPT" }, + { LLAssetType::AT_CLOTHING, "CLOTHING" }, + { LLAssetType::AT_OBJECT, "OBJECT" }, + { LLAssetType::AT_NOTECARD, "NOTECARD" }, + { LLAssetType::AT_CATEGORY, "CATEGORY" }, + { LLAssetType::AT_LSL_TEXT, "LSL_TEXT" }, + { LLAssetType::AT_LSL_BYTECODE, "LSL_BYTECODE" }, + { LLAssetType::AT_TEXTURE_TGA, "TEXTURE_TGA" }, + { LLAssetType::AT_BODYPART, "BODYPART" }, + { LLAssetType::AT_SOUND_WAV, "SOUND_WAV" }, + { LLAssetType::AT_IMAGE_TGA, "IMAGE_TGA" }, + { LLAssetType::AT_IMAGE_JPEG, "IMAGE_JPEG" }, + { LLAssetType::AT_ANIMATION, "ANIMATION" }, + { LLAssetType::AT_GESTURE, "GESTURE" }, + { LLAssetType::AT_SIMSTATE, "SIMSTATE" }, + { LLAssetType::AT_LINK, "LINK" }, + { LLAssetType::AT_LINK_FOLDER, "LINK_FOLDER" }, + { LLAssetType::AT_MARKETPLACE_FOLDER, "MARKETPLACE_FOLDER" }, + { LLAssetType::AT_WIDGET, "WIDGET" }, + { LLAssetType::AT_PERSON, "PERSON" }, + { LLAssetType::AT_MESH, "MESH" }, + { LLAssetType::AT_SETTINGS, "SETTINGS" }, + { LLAssetType::AT_UNKNOWN, "UNKNOWN" } + }; + + asset_type_to_name_t::iterator iter = asset_type_to_name.find(at); + if (iter != asset_type_to_name.end()) + { + return iter->second; + } + + return std::string("UNKNOWN"); +} + +const std::string idToFilepath(const std::string id, LLAssetType::EType at) +{ + /** + * For the moment this is just {UUID}_{ASSET_TYPE}.txt but of + * course, will be greatly expanded upon + */ + std::ostringstream ss; + ss << "00cache_"; + ss << id; + ss << "_"; + ss << assetTypeToString(at); + ss << ".txt"; + + const std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ss.str()); + + return filepath; +} + +// static +bool LLDiskCache::getExists(const LLUUID &file_id, const LLAssetType::EType file_type) +{ + std::string id_str; + file_id.toString(id_str); + const std::string filename = idToFilepath(id_str, file_type); + + std::ifstream file(filename, std::ios::binary); + if (file.is_open()) + { + file.seekg(0, std::ios::end); + return file.tellg() > 0; + } + return false; +} + +// static +bool LLDiskCache::removeFile(const LLUUID &file_id, const LLAssetType::EType file_type) +{ + std::string id_str; + file_id.toString(id_str); + const std::string filename = idToFilepath(id_str, file_type); + + std::remove(filename.c_str()); + + return true; +} + +// static +bool LLDiskCache::renameFile(const LLUUID &old_file_id, const LLAssetType::EType old_file_type, + const LLUUID &new_file_id, const LLAssetType::EType new_file_type) +{ + std::string old_id_str; + old_file_id.toString(old_id_str); + const std::string old_filename = idToFilepath(old_id_str, old_file_type); + + std::string new_id_str; + new_file_id.toString(new_id_str); + const std::string new_filename = idToFilepath(new_id_str, new_file_type); + + if (std::rename(old_filename.c_str(), new_filename.c_str())) + { + // We would like to return FALSE here indicating the operation + // failed but the original code does not and doing so seems to + // break a lot of things so we go with the flow... + //return FALSE; + } + + return TRUE; +} + +// static +S32 LLDiskCache::getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type) +{ + std::string id_str; + file_id.toString(id_str); + const std::string filename = idToFilepath(id_str, file_type); + + S32 file_size = 0; + std::ifstream file(filename, std::ios::binary); + if (file.is_open()) + { + file.seekg(0, std::ios::end); + file_size = file.tellg(); + } + + return file_size; +} + +BOOL LLDiskCache::read(U8 *buffer, S32 bytes, BOOL async, F32 priority) +{ + BOOL success = TRUE; + + mReadComplete = FALSE; + + std::string id; + mFileID.toString(id); + const std::string filename = idToFilepath(id, mFileType); + + std::ifstream file(filename, std::ios::binary); + if (file.is_open()) + { + file.seekg(mPosition, std::ios::beg); + + file.read((char*)buffer, bytes); + + if (file) + { + mBytesRead = bytes; + } + else + { + mBytesRead = file.gcount(); + } + + file.close(); + + mPosition += mBytesRead; + if (!mBytesRead) + { + success = FALSE; + } + + mReadComplete = TRUE; + } + + return success; +} + +BOOL LLDiskCache::isReadComplete() +{ + if (mReadComplete) + { + return TRUE; + } + + return FALSE; +} + +S32 LLDiskCache::getLastBytesRead() +{ + return mBytesRead; +} + +BOOL LLDiskCache::eof() +{ + return mPosition >= getSize(); +} + +BOOL LLDiskCache::write(const U8 *buffer, S32 bytes) +{ + std::string id_str; + mFileID.toString(id_str); + const std::string filename = idToFilepath(id_str, mFileType); + + BOOL success = FALSE; + + if (mMode == APPEND) + { + std::ofstream ofs(filename, std::ios::app | std::ios::binary); + if (ofs) + { + ofs.write((const char*)buffer, bytes); + + success = TRUE; + } + } + else + { + std::ofstream ofs(filename, std::ios::binary); + if (ofs) + { + ofs.write((const char*)buffer, bytes); + + mPosition += bytes; + + success = TRUE; + } + } + + return success; +} + +//static +BOOL LLDiskCache::writeFile(const U8 *buffer, S32 bytes, const LLUUID &uuid, LLAssetType::EType type) +{ + LLDiskCache file(uuid, type, LLDiskCache::WRITE); + file.setMaxSize(bytes); + return file.write(buffer, bytes); +} + +BOOL LLDiskCache::seek(S32 offset, S32 origin) +{ + if (-1 == origin) + { + origin = mPosition; + } + + S32 new_pos = origin + offset; + + S32 size = getSize(); + + if (new_pos > size) + { + LL_WARNS() << "Attempt to seek past end of file" << LL_ENDL; + + mPosition = size; + return FALSE; + } + else if (new_pos < 0) + { + LL_WARNS() << "Attempt to seek past beginning of file" << LL_ENDL; + + mPosition = 0; + return FALSE; + } + + mPosition = new_pos; + return TRUE; +} + +S32 LLDiskCache::tell() const +{ + return mPosition; +} + +S32 LLDiskCache::getSize() +{ + return LLDiskCache::getFileSize(mFileID, mFileType); +} + +S32 LLDiskCache::getMaxSize() +{ + // offer up a huge size since we don't care what the max is + return INT_MAX; +} + +BOOL LLDiskCache::setMaxSize(S32 size) +{ + // we don't care what the max size is so we do nothing + // and return true to indicate all was okay + return TRUE; +} + +BOOL LLDiskCache::rename(const LLUUID &new_id, const LLAssetType::EType new_type) +{ + LLDiskCache::renameFile(mFileID, mFileType, new_id, new_type); + + mFileID = new_id; + mFileType = new_type; + + return TRUE; +} + +BOOL LLDiskCache::remove() +{ + LLDiskCache::removeFile(mFileID, mFileType); + + return TRUE; +} + +// static +void LLDiskCache::initClass() +{ +} + +// static +void LLDiskCache::cleanupClass() +{ +} + +bool LLDiskCache::isLocked() +{ + // I don't think we care about this test since there is no locking + // TODO: remove this function and calling sites? + return FALSE; +} + +void LLDiskCache::waitForLock() +{ + // TODO: remove this function and calling sites? +} diff --git a/indra/llfilesystem/lldiskcache.h b/indra/llfilesystem/lldiskcache.h new file mode 100644 index 0000000000..7ad06a8689 --- /dev/null +++ b/indra/llfilesystem/lldiskcache.h @@ -0,0 +1,82 @@ +/** + * @file lldiskcacke.h + * @brief Definition of virtual file + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDISKCACHE_H +#define LL_LLDISKCACHE_H + +#include "lluuid.h" +#include "llassettype.h" + +class LLDiskCache +{ +public: + LLDiskCache(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode = LLDiskCache::READ); + ~LLDiskCache(); + + BOOL read(U8 *buffer, S32 bytes, BOOL async = FALSE, F32 priority = 128.f); /* Flawfinder: ignore */ + BOOL isReadComplete(); + S32 getLastBytesRead(); + BOOL eof(); + + BOOL write(const U8 *buffer, S32 bytes); + static BOOL writeFile(const U8 *buffer, S32 bytes, const LLUUID &uuid, LLAssetType::EType type); + BOOL seek(S32 offset, S32 origin = -1); + S32 tell() const; + + S32 getSize(); + S32 getMaxSize(); + BOOL setMaxSize(S32 size); + BOOL rename(const LLUUID &new_id, const LLAssetType::EType new_type); + BOOL remove(); + + bool isLocked(); + void waitForLock(); + + static bool getExists(const LLUUID &file_id, const LLAssetType::EType file_type); + static bool removeFile(const LLUUID &file_id, const LLAssetType::EType file_type); + 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 S32 getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type); + + static void initClass(); + static void cleanupClass(); + +public: + static const S32 READ; + static const S32 WRITE; + static const S32 READ_WRITE; + static const S32 APPEND; + +protected: + LLAssetType::EType mFileType; + BOOL mReadComplete; + LLUUID mFileID; + S32 mPosition; + S32 mMode; + S32 mBytesRead; +}; + +#endif // LL_LLDISKCACHE_H diff --git a/indra/llfilesystem/lllfsthread.cpp b/indra/llfilesystem/lllfsthread.cpp new file mode 100644 index 0000000000..be8e83a56f --- /dev/null +++ b/indra/llfilesystem/lllfsthread.cpp @@ -0,0 +1,245 @@ +/** + * @file lllfsthread.cpp + * @brief LLLFSThread base class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "lllfsthread.h" +#include "llstl.h" +#include "llapr.h" + +//============================================================================ + +/*static*/ LLLFSThread* LLLFSThread::sLocal = NULL; + +//============================================================================ +// Run on MAIN thread +//static +void LLLFSThread::initClass(bool local_is_threaded) +{ + llassert(sLocal == NULL); + sLocal = new LLLFSThread(local_is_threaded); +} + +//static +S32 LLLFSThread::updateClass(U32 ms_elapsed) +{ + sLocal->update((F32)ms_elapsed); + return sLocal->getPending(); +} + +//static +void LLLFSThread::cleanupClass() +{ + llassert(sLocal != NULL); + sLocal->setQuitting(); + while (sLocal->getPending()) + { + sLocal->update(0); + } + delete sLocal; + sLocal = NULL; +} + +//---------------------------------------------------------------------------- + +LLLFSThread::LLLFSThread(bool threaded) : + LLQueuedThread("LFS", threaded), + mPriorityCounter(PRIORITY_LOWBITS) +{ + if(!mLocalAPRFilePoolp) + { + mLocalAPRFilePoolp = new LLVolatileAPRPool() ; + } +} + +LLLFSThread::~LLLFSThread() +{ + // mLocalAPRFilePoolp cleanup in LLThread + // ~LLQueuedThread() will be called here +} + +//---------------------------------------------------------------------------- + +LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfinder: ignore */ + U8* buffer, S32 offset, S32 numbytes, + Responder* responder, U32 priority) +{ + handle_t handle = generateHandle(); + + if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter(); + else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW; // All reads are at least PRIORITY_LOW + + Request* req = new Request(this, handle, priority, + FILE_READ, filename, + buffer, offset, numbytes, + responder); + + bool res = addRequest(req); + if (!res) + { + LL_ERRS() << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << LL_ENDL; + } + + return handle; +} + +LLLFSThread::handle_t LLLFSThread::write(const std::string& filename, + U8* buffer, S32 offset, S32 numbytes, + Responder* responder, U32 priority) +{ + handle_t handle = generateHandle(); + + if (priority == 0) priority = PRIORITY_LOW | priorityCounter(); + + Request* req = new Request(this, handle, priority, + FILE_WRITE, filename, + buffer, offset, numbytes, + responder); + + bool res = addRequest(req); + if (!res) + { + LL_ERRS() << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << LL_ENDL; + } + + return handle; +} + +//============================================================================ + +LLLFSThread::Request::Request(LLLFSThread* thread, + handle_t handle, U32 priority, + operation_t op, const std::string& filename, + U8* buffer, S32 offset, S32 numbytes, + Responder* responder) : + QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE), + mThread(thread), + mOperation(op), + mFileName(filename), + mBuffer(buffer), + mOffset(offset), + mBytes(numbytes), + mBytesRead(0), + mResponder(responder) +{ + if (numbytes <= 0) + { + LL_WARNS() << "LLLFSThread: Request with numbytes = " << numbytes << LL_ENDL; + } +} + +LLLFSThread::Request::~Request() +{ +} + +// virtual, called from own thread +void LLLFSThread::Request::finishRequest(bool completed) +{ + if (mResponder.notNull()) + { + mResponder->completed(completed ? mBytesRead : 0); + mResponder = NULL; + } +} + +void LLLFSThread::Request::deleteRequest() +{ + if (getStatus() == STATUS_QUEUED) + { + LL_ERRS() << "Attempt to delete a queued LLLFSThread::Request!" << LL_ENDL; + } + if (mResponder.notNull()) + { + mResponder->completed(0); + mResponder = NULL; + } + LLQueuedThread::QueuedRequest::deleteRequest(); +} + +bool LLLFSThread::Request::processRequest() +{ + bool complete = false; + if (mOperation == FILE_READ) + { + llassert(mOffset >= 0); + LLAPRFile infile ; // auto-closes + infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool()); + if (!infile.getFileHandle()) + { + LL_WARNS() << "LLLFS: Unable to read file: " << mFileName << LL_ENDL; + mBytesRead = 0; // fail + return true; + } + S32 off; + if (mOffset < 0) + off = infile.seek(APR_END, 0); + else + off = infile.seek(APR_SET, mOffset); + llassert_always(off >= 0); + mBytesRead = infile.read(mBuffer, mBytes ); + complete = true; +// LL_INFOS() << "LLLFSThread::READ:" << mFileName << " Bytes: " << mBytesRead << LL_ENDL; + } + else if (mOperation == FILE_WRITE) + { + apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; + if (mOffset < 0) + flags |= APR_APPEND; + LLAPRFile outfile ; // auto-closes + outfile.open(mFileName, flags, mThread->getLocalAPRFilePool()); + if (!outfile.getFileHandle()) + { + LL_WARNS() << "LLLFS: Unable to write file: " << mFileName << LL_ENDL; + mBytesRead = 0; // fail + return true; + } + if (mOffset >= 0) + { + S32 seek = outfile.seek(APR_SET, mOffset); + if (seek < 0) + { + LL_WARNS() << "LLLFS: Unable to write file (seek failed): " << mFileName << LL_ENDL; + mBytesRead = 0; // fail + return true; + } + } + mBytesRead = outfile.write(mBuffer, mBytes ); + complete = true; +// LL_INFOS() << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << LL_ENDL; + } + else + { + LL_ERRS() << "LLLFSThread::unknown operation: " << (S32)mOperation << LL_ENDL; + } + return complete; +} + +//============================================================================ + +LLLFSThread::Responder::~Responder() +{ +} + +//============================================================================ diff --git a/indra/llfilesystem/lllfsthread.h b/indra/llfilesystem/lllfsthread.h new file mode 100644 index 0000000000..58f658f7ba --- /dev/null +++ b/indra/llfilesystem/lllfsthread.h @@ -0,0 +1,147 @@ +/** + * @file lllfsthread.h + * @brief LLLFSThread base class + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLLFSTHREAD_H +#define LL_LLLFSTHREAD_H + +#include +#include +#include +#include + +#include "llpointer.h" +#include "llqueuedthread.h" + +//============================================================================ +// Threaded Local File System +//============================================================================ + +class LLLFSThread : public LLQueuedThread +{ + //------------------------------------------------------------------------ +public: + enum operation_t { + FILE_READ, + FILE_WRITE, + FILE_RENAME, + FILE_REMOVE + }; + + //------------------------------------------------------------------------ +public: + + class Responder : public LLThreadSafeRefCount + { + protected: + ~Responder(); + public: + virtual void completed(S32 bytes) = 0; + }; + + class Request : public QueuedRequest + { + protected: + virtual ~Request(); // use deleteRequest() + + public: + Request(LLLFSThread* thread, + handle_t handle, U32 priority, + operation_t op, const std::string& filename, + U8* buffer, S32 offset, S32 numbytes, + Responder* responder); + + S32 getBytes() + { + return mBytes; + } + S32 getBytesRead() + { + return mBytesRead; + } + S32 getOperation() + { + return mOperation; + } + U8* getBuffer() + { + return mBuffer; + } + const std::string& getFilename() + { + return mFileName; + } + + /*virtual*/ bool processRequest(); + /*virtual*/ void finishRequest(bool completed); + /*virtual*/ void deleteRequest(); + + private: + LLLFSThread* mThread; + operation_t mOperation; + + std::string mFileName; + + U8* mBuffer; // dest for reads, source for writes, new UUID for rename + S32 mOffset; // offset into file, -1 = append (WRITE only) + S32 mBytes; // bytes to read from file, -1 = all + S32 mBytesRead; // bytes read from file + + LLPointer mResponder; + }; + + //------------------------------------------------------------------------ +public: + LLLFSThread(bool threaded = TRUE); + ~LLLFSThread(); + + // Return a Request handle + handle_t read(const std::string& filename, /* Flawfinder: ignore */ + U8* buffer, S32 offset, S32 numbytes, + Responder* responder, U32 pri=0); + handle_t write(const std::string& filename, + U8* buffer, S32 offset, S32 numbytes, + Responder* responder, U32 pri=0); + + // Misc + U32 priorityCounter() { return mPriorityCounter-- & PRIORITY_LOWBITS; } // Use to order IO operations + + // static initializers + static void initClass(bool local_is_threaded = TRUE); // Setup sLocal + static S32 updateClass(U32 ms_elapsed); + static void cleanupClass(); // Delete sLocal + + +private: + U32 mPriorityCounter; + +public: + static LLLFSThread* sLocal; // Default local file thread +}; + +//============================================================================ + + +#endif // LL_LLLFSTHREAD_H diff --git a/indra/llfilesystem/tests/lldir_test.cpp b/indra/llfilesystem/tests/lldir_test.cpp new file mode 100644 index 0000000000..3cff622a4b --- /dev/null +++ b/indra/llfilesystem/tests/lldir_test.cpp @@ -0,0 +1,767 @@ +/** + * @file lldir_test.cpp + * @date 2008-05 + * @brief LLDir test cases. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llstring.h" +#include "tests/StringVec.h" +#include "../lldir.h" +#include "../lldiriterator.h" + +#include "../test/lltut.h" +#include "stringize.h" +#include +#include + +using boost::assign::list_of; + +// We use ensure_equals(..., vec(list_of(...))) not because it's functionally +// required, but because ensure_equals() knows how to format a StringVec. +// Turns out that when ensure_equals() displays a test failure with just +// list_of("string")("another"), you see 'stringanother' vs. '("string", +// "another")'. +StringVec vec(const StringVec& v) +{ + return v; +} + +// For some tests, use a dummy LLDir that uses memory data instead of touching +// the filesystem +struct LLDir_Dummy: public LLDir +{ + /*----------------------------- LLDir API ------------------------------*/ + LLDir_Dummy() + { + // Initialize important LLDir data members based on the filesystem + // data below. + mDirDelimiter = "/"; + mExecutableDir = "install"; + mExecutableFilename = "test"; + mExecutablePathAndName = add(mExecutableDir, mExecutableFilename); + mWorkingDir = mExecutableDir; + mAppRODataDir = "install"; + mSkinBaseDir = add(mAppRODataDir, "skins"); + mOSUserDir = "user"; + mOSUserAppDir = mOSUserDir; + mLindenUserDir = ""; + + // Make the dummy filesystem look more or less like what we expect in + // the real one. + static const char* preload[] = + { + // We group these fixture-data pathnames by basename, rather than + // sorting by full path as you might expect, because the outcome + // of each test strongly depends on which skins/languages provide + // a given basename. + "install/skins/default/colors.xml", + "install/skins/steam/colors.xml", + "user/skins/default/colors.xml", + "user/skins/steam/colors.xml", + + "install/skins/default/xui/en/strings.xml", + "install/skins/default/xui/fr/strings.xml", + "install/skins/steam/xui/en/strings.xml", + "install/skins/steam/xui/fr/strings.xml", + "user/skins/default/xui/en/strings.xml", + "user/skins/default/xui/fr/strings.xml", + "user/skins/steam/xui/en/strings.xml", + "user/skins/steam/xui/fr/strings.xml", + + "install/skins/default/xui/en/floater.xml", + "install/skins/default/xui/fr/floater.xml", + "user/skins/default/xui/fr/floater.xml", + + "install/skins/default/xui/en/newfile.xml", + "install/skins/default/xui/fr/newfile.xml", + "user/skins/default/xui/en/newfile.xml", + + "install/skins/default/html/en-us/welcome.html", + "install/skins/default/html/fr/welcome.html", + + "install/skins/default/textures/only_default.jpeg", + "install/skins/steam/textures/only_steam.jpeg", + "user/skins/default/textures/only_user_default.jpeg", + "user/skins/steam/textures/only_user_steam.jpeg", + + "install/skins/default/future/somefile.txt" + }; + BOOST_FOREACH(const char* path, preload) + { + buildFilesystem(path); + } + } + + virtual ~LLDir_Dummy() {} + + virtual void initAppDirs(const std::string& app_name, const std::string& app_read_only_data_dir) + { + // Implement this when we write a test that needs it + } + + virtual std::string getCurPath() + { + // Implement this when we write a test that needs it + return ""; + } + + virtual U32 countFilesInDir(const std::string& dirname, const std::string& mask) + { + // Implement this when we write a test that needs it + return 0; + } + + virtual bool fileExists(const std::string& pathname) const + { + // Record fileExists() calls so we can check whether caching is + // working right. Certain LLDir calls should be able to make decisions + // without calling fileExists() again, having already checked existence. + mChecked.insert(pathname); + // For our simple flat set of strings, see whether the identical + // pathname exists in our set. + return (mFilesystem.find(pathname) != mFilesystem.end()); + } + + virtual std::string getLLPluginLauncher() + { + // Implement this when we write a test that needs it + return ""; + } + + virtual std::string getLLPluginFilename(std::string base_name) + { + // Implement this when we write a test that needs it + return ""; + } + + /*----------------------------- Dummy data -----------------------------*/ + void clearFilesystem() { mFilesystem.clear(); } + void buildFilesystem(const std::string& path) + { + // Split the pathname on slashes, ignoring leading, trailing, doubles + StringVec components; + LLStringUtil::getTokens(path, components, "/"); + // Ensure we have an entry representing every level of this path + std::string partial; + BOOST_FOREACH(std::string component, components) + { + append(partial, component); + mFilesystem.insert(partial); + } + } + + void clear_checked() { mChecked.clear(); } + void ensure_checked(const std::string& pathname) const + { + tut::ensure(STRINGIZE(pathname << " was not checked but should have been"), + mChecked.find(pathname) != mChecked.end()); + } + void ensure_not_checked(const std::string& pathname) const + { + tut::ensure(STRINGIZE(pathname << " was checked but should not have been"), + mChecked.find(pathname) == mChecked.end()); + } + + std::set mFilesystem; + mutable std::set mChecked; +}; + +namespace tut +{ + struct LLDirTest + { + }; + typedef test_group LLDirTest_t; + typedef LLDirTest_t::object LLDirTest_object_t; + tut::LLDirTest_t tut_LLDirTest("LLDir"); + + template<> template<> + void LLDirTest_object_t::test<1>() + // getDirDelimiter + { + ensure("getDirDelimiter", !gDirUtilp->getDirDelimiter().empty()); + } + + template<> template<> + void LLDirTest_object_t::test<2>() + // getBaseFileName + { + std::string delim = gDirUtilp->getDirDelimiter(); + std::string rawFile = "foo"; + std::string rawFileExt = "foo.bAr"; + std::string rawFileNullExt = "foo."; + std::string rawExt = ".bAr"; + std::string rawDot = "."; + std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; + std::string pathExt = pathNoExt + ".eXt"; + std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; + std::string dottedPathExt = dottedPathNoExt + ".eXt"; + + // foo[.bAr] + + ensure_equals("getBaseFileName/r-no-ext/no-strip-exten", + gDirUtilp->getBaseFileName(rawFile, false), + "foo"); + + ensure_equals("getBaseFileName/r-no-ext/strip-exten", + gDirUtilp->getBaseFileName(rawFile, true), + "foo"); + + ensure_equals("getBaseFileName/r-ext/no-strip-exten", + gDirUtilp->getBaseFileName(rawFileExt, false), + "foo.bAr"); + + ensure_equals("getBaseFileName/r-ext/strip-exten", + gDirUtilp->getBaseFileName(rawFileExt, true), + "foo"); + + // foo. + + ensure_equals("getBaseFileName/rn-no-ext/no-strip-exten", + gDirUtilp->getBaseFileName(rawFileNullExt, false), + "foo."); + + ensure_equals("getBaseFileName/rn-no-ext/strip-exten", + gDirUtilp->getBaseFileName(rawFileNullExt, true), + "foo"); + + // .bAr + // interesting case - with no basename, this IS the basename, not the extension. + + ensure_equals("getBaseFileName/e-ext/no-strip-exten", + gDirUtilp->getBaseFileName(rawExt, false), + ".bAr"); + + ensure_equals("getBaseFileName/e-ext/strip-exten", + gDirUtilp->getBaseFileName(rawExt, true), + ".bAr"); + + // . + + ensure_equals("getBaseFileName/d/no-strip-exten", + gDirUtilp->getBaseFileName(rawDot, false), + "."); + + ensure_equals("getBaseFileName/d/strip-exten", + gDirUtilp->getBaseFileName(rawDot, true), + "."); + + // aa/bb/cc/dd/ee[.eXt] + + ensure_equals("getBaseFileName/no-ext/no-strip-exten", + gDirUtilp->getBaseFileName(pathNoExt, false), + "ee"); + + ensure_equals("getBaseFileName/no-ext/strip-exten", + gDirUtilp->getBaseFileName(pathNoExt, true), + "ee"); + + ensure_equals("getBaseFileName/ext/no-strip-exten", + gDirUtilp->getBaseFileName(pathExt, false), + "ee.eXt"); + + ensure_equals("getBaseFileName/ext/strip-exten", + gDirUtilp->getBaseFileName(pathExt, true), + "ee"); + + // aa/bb/cc.dd/ee[.eXt] + + ensure_equals("getBaseFileName/d-no-ext/no-strip-exten", + gDirUtilp->getBaseFileName(dottedPathNoExt, false), + "ee"); + + ensure_equals("getBaseFileName/d-no-ext/strip-exten", + gDirUtilp->getBaseFileName(dottedPathNoExt, true), + "ee"); + + ensure_equals("getBaseFileName/d-ext/no-strip-exten", + gDirUtilp->getBaseFileName(dottedPathExt, false), + "ee.eXt"); + + ensure_equals("getBaseFileName/d-ext/strip-exten", + gDirUtilp->getBaseFileName(dottedPathExt, true), + "ee"); + } + + template<> template<> + void LLDirTest_object_t::test<3>() + // getDirName + { + std::string delim = gDirUtilp->getDirDelimiter(); + std::string rawFile = "foo"; + std::string rawFileExt = "foo.bAr"; + std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; + std::string pathExt = pathNoExt + ".eXt"; + std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; + std::string dottedPathExt = dottedPathNoExt + ".eXt"; + + // foo[.bAr] + + ensure_equals("getDirName/r-no-ext", + gDirUtilp->getDirName(rawFile), + ""); + + ensure_equals("getDirName/r-ext", + gDirUtilp->getDirName(rawFileExt), + ""); + + // aa/bb/cc/dd/ee[.eXt] + + ensure_equals("getDirName/no-ext", + gDirUtilp->getDirName(pathNoExt), + "aa" + delim + "bb" + delim + "cc" + delim + "dd"); + + ensure_equals("getDirName/ext", + gDirUtilp->getDirName(pathExt), + "aa" + delim + "bb" + delim + "cc" + delim + "dd"); + + // aa/bb/cc.dd/ee[.eXt] + + ensure_equals("getDirName/d-no-ext", + gDirUtilp->getDirName(dottedPathNoExt), + "aa" + delim + "bb" + delim + "cc.dd"); + + ensure_equals("getDirName/d-ext", + gDirUtilp->getDirName(dottedPathExt), + "aa" + delim + "bb" + delim + "cc.dd"); + } + + template<> template<> + void LLDirTest_object_t::test<4>() + // getExtension + { + std::string delim = gDirUtilp->getDirDelimiter(); + std::string rawFile = "foo"; + std::string rawFileExt = "foo.bAr"; + std::string rawFileNullExt = "foo."; + std::string rawExt = ".bAr"; + std::string rawDot = "."; + std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; + std::string pathExt = pathNoExt + ".eXt"; + std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; + std::string dottedPathExt = dottedPathNoExt + ".eXt"; + + // foo[.bAr] + + ensure_equals("getExtension/r-no-ext", + gDirUtilp->getExtension(rawFile), + ""); + + ensure_equals("getExtension/r-ext", + gDirUtilp->getExtension(rawFileExt), + "bar"); + + // foo. + + ensure_equals("getExtension/rn-no-ext", + gDirUtilp->getExtension(rawFileNullExt), + ""); + + // .bAr + // interesting case - with no basename, this IS the basename, not the extension. + + ensure_equals("getExtension/e-ext", + gDirUtilp->getExtension(rawExt), + ""); + + // . + + ensure_equals("getExtension/d", + gDirUtilp->getExtension(rawDot), + ""); + + // aa/bb/cc/dd/ee[.eXt] + + ensure_equals("getExtension/no-ext", + gDirUtilp->getExtension(pathNoExt), + ""); + + ensure_equals("getExtension/ext", + gDirUtilp->getExtension(pathExt), + "ext"); + + // aa/bb/cc.dd/ee[.eXt] + + ensure_equals("getExtension/d-no-ext", + gDirUtilp->getExtension(dottedPathNoExt), + ""); + + ensure_equals("getExtension/d-ext", + gDirUtilp->getExtension(dottedPathExt), + "ext"); + } + + std::string makeTestFile( const std::string& dir, const std::string& file ) + { + std::string path = dir + file; + LLFILE* handle = LLFile::fopen( path, "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." + ensure("failed to write to test file '"+path+"'", EOF != fputs("test file", handle) ); + fclose(handle); + return path; + } + + std::string makeTestDir( const std::string& dirbase ) + { + int counter; + std::string uniqueDir; + bool foundUnused; + std::string delim = gDirUtilp->getDirDelimiter(); + + for (counter=0, foundUnused=false; !foundUnused; counter++ ) + { + char counterStr[3]; + sprintf(counterStr, "%02d", counter); + uniqueDir = dirbase + counterStr; + foundUnused = ! ( LLFile::isdir(uniqueDir) || LLFile::isfile(uniqueDir) ); + } + ensure("test directory '" + uniqueDir + "' creation failed", !LLFile::mkdir(uniqueDir)); + + return uniqueDir + delim; // HACK - apparently, the trailing delimiter is needed... + } + + static const char* DirScanFilename[5] = { "file1.abc", "file2.abc", "file1.xyz", "file2.xyz", "file1.mno" }; + + void scanTest(const std::string& directory, const std::string& pattern, bool correctResult[5]) + { + + // Scan directory and see if any file1.* files are found + std::string scanResult; + int found = 0; + bool filesFound[5] = { false, false, false, false, false }; + //std::cerr << "searching '"+directory+"' for '"+pattern+"'\n"; + + LLDirIterator iter(directory, pattern); + while ( found <= 5 && iter.next(scanResult) ) + { + found++; + //std::cerr << " found '"+scanResult+"'\n"; + int check; + for (check=0; check < 5 && ! ( scanResult == DirScanFilename[check] ); check++) + { + } + // check is now either 5 (not found) or the index of the matching name + if (check < 5) + { + ensure( "found file '"+(std::string)DirScanFilename[check]+"' twice", ! filesFound[check] ); + filesFound[check] = true; + } + else // check is 5 - should not happen + { + fail( "found unknown file '"+scanResult+"'"); + } + } + for (int i=0; i<5; i++) + { + if (correctResult[i]) + { + ensure("scan of '"+directory+"' using '"+pattern+"' did not return '"+DirScanFilename[i]+"'", filesFound[i]); + } + else + { + ensure("scan of '"+directory+"' using '"+pattern+"' incorrectly returned '"+DirScanFilename[i]+"'", !filesFound[i]); + } + } + } + + template<> template<> + void LLDirTest_object_t::test<5>() + // LLDirIterator::next + { + std::string delim = gDirUtilp->getDirDelimiter(); + std::string dirTemp = LLFile::tmpdir(); + + // Create the same 5 file names of the two directories + + std::string dir1 = makeTestDir(dirTemp + "LLDirIterator"); + std::string dir2 = makeTestDir(dirTemp + "LLDirIterator"); + std::string dir1files[5]; + std::string dir2files[5]; + for (int i=0; i<5; i++) + { + dir1files[i] = makeTestFile(dir1, DirScanFilename[i]); + dir2files[i] = makeTestFile(dir2, DirScanFilename[i]); + } + + // Scan dir1 and see if each of the 5 files is found exactly once + bool expected1[5] = { true, true, true, true, true }; + scanTest(dir1, "*", expected1); + + // Scan dir2 and see if only the 2 *.xyz files are found + bool expected2[5] = { false, false, true, true, false }; + scanTest(dir1, "*.xyz", expected2); + + // Scan dir2 and see if only the 1 *.mno file is found + bool expected3[5] = { false, false, false, false, true }; + scanTest(dir2, "*.mno", expected3); + + // Scan dir1 and see if any *.foo files are found + bool expected4[5] = { false, false, false, false, false }; + scanTest(dir1, "*.foo", expected4); + + // Scan dir1 and see if any file1.* files are found + bool expected5[5] = { true, false, true, false, true }; + scanTest(dir1, "file1.*", expected5); + + // Scan dir1 and see if any file1.* files are found + bool expected6[5] = { true, true, false, false, false }; + scanTest(dir1, "file?.abc", expected6); + + // Scan dir2 and see if any file?.x?z files are found + bool expected7[5] = { false, false, true, true, false }; + scanTest(dir2, "file?.x?z", expected7); + + // Scan dir2 and see if any file?.??c files are found + bool expected8[5] = { true, true, false, false, false }; + scanTest(dir2, "file?.??c", expected8); + scanTest(dir2, "*.??c", expected8); + + // Scan dir1 and see if any *.?n? files are found + bool expected9[5] = { false, false, false, false, true }; + scanTest(dir1, "*.?n?", expected9); + + // Scan dir1 and see if any *.???? files are found + bool expected10[5] = { false, false, false, false, false }; + scanTest(dir1, "*.????", expected10); + + // Scan dir1 and see if any ?????.* files are found + bool expected11[5] = { true, true, true, true, true }; + scanTest(dir1, "?????.*", expected11); + + // Scan dir1 and see if any ??l??.xyz files are found + bool expected12[5] = { false, false, true, true, false }; + scanTest(dir1, "??l??.xyz", expected12); + + bool expected13[5] = { true, false, true, false, false }; + scanTest(dir1, "file1.{abc,xyz}", expected13); + + bool expected14[5] = { true, true, false, false, false }; + scanTest(dir1, "file[0-9].abc", expected14); + + bool expected15[5] = { true, true, false, false, false }; + scanTest(dir1, "file[!a-z].abc", expected15); + + // clean up all test files and directories + for (int i=0; i<5; i++) + { + LLFile::remove(dir1files[i]); + LLFile::remove(dir2files[i]); + } + LLFile::rmdir(dir1); + LLFile::rmdir(dir2); + } + + template<> template<> + void LLDirTest_object_t::test<6>() + { + set_test_name("findSkinnedFilenames()"); + LLDir_Dummy lldir; + /*------------------------ "default", "en" -------------------------*/ + // Setting "default" means we shouldn't consider any "*/skins/steam" + // directories; setting "en" means we shouldn't consider any "xui/fr" + // directories. + lldir.setSkinFolder("default", "en"); + ensure_equals(lldir.getSkinFolder(), "default"); + ensure_equals(lldir.getLanguage(), "en"); + + // top-level directory of a skin isn't localized + ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS), + vec(list_of("install/skins/default/colors.xml") + ("user/skins/default/colors.xml"))); + // We should not have needed to check for skins/default/en. We should + // just "know" that SKINBASE is not localized. + lldir.ensure_not_checked("install/skins/default/en"); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_default.jpeg"), + vec(list_of("install/skins/default/textures/only_default.jpeg"))); + // Nor should we have needed to check skins/default/textures/en + // because textures is known not to be localized. + lldir.ensure_not_checked("install/skins/default/textures/en"); + + StringVec expected(vec(list_of("install/skins/default/xui/en/strings.xml") + ("user/skins/default/xui/en/strings.xml"))); + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), + expected); + // The first time, we had to probe to find out whether xui was localized. + lldir.ensure_checked("install/skins/default/xui/en"); + lldir.clear_checked(); + // Now make the same call again -- should return same result -- + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), + expected); + // but this time it should remember that xui is localized. + lldir.ensure_not_checked("install/skins/default/xui/en"); + + // localized subdir with "en-us" instead of "en" + ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), + vec(list_of("install/skins/default/html/en-us/welcome.html"))); + lldir.ensure_checked("install/skins/default/html/en"); + lldir.ensure_checked("install/skins/default/html/en-us"); + lldir.clear_checked(); + ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), + vec(list_of("install/skins/default/html/en-us/welcome.html"))); + lldir.ensure_not_checked("install/skins/default/html/en"); + lldir.ensure_not_checked("install/skins/default/html/en-us"); + + ensure_equals(lldir.findSkinnedFilenames("future", "somefile.txt"), + vec(list_of("install/skins/default/future/somefile.txt"))); + // Test probing for an unrecognized unlocalized future subdir. + lldir.ensure_checked("install/skins/default/future/en"); + lldir.clear_checked(); + ensure_equals(lldir.findSkinnedFilenames("future", "somefile.txt"), + vec(list_of("install/skins/default/future/somefile.txt"))); + // Second time it should remember that future is unlocalized. + lldir.ensure_not_checked("install/skins/default/future/en"); + + // When language is set to "en", requesting an html file pulls up the + // "en-us" version -- not because it magically matches those strings, + // but because there's no "en" localization and it falls back on the + // default "en-us"! Note that it would probably still be better to + // make the default localization be "en" and allow "en-gb" (or + // whatever) localizations, which would work much more the way you'd + // expect. + ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), + vec(list_of("install/skins/default/html/en-us/welcome.html"))); + + /*------------------------ "default", "fr" -------------------------*/ + // We start being able to distinguish localized subdirs from + // unlocalized when we ask for a non-English language. + lldir.setSkinFolder("default", "fr"); + ensure_equals(lldir.getLanguage(), "fr"); + + // pass merge=true to request this filename in all relevant skins + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), + vec(list_of + ("install/skins/default/xui/en/strings.xml") + ("install/skins/default/xui/fr/strings.xml") + ("user/skins/default/xui/en/strings.xml") + ("user/skins/default/xui/fr/strings.xml"))); + + // pass (or default) merge=false to request only most specific skin + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), + vec(list_of + ("user/skins/default/xui/en/strings.xml") + ("user/skins/default/xui/fr/strings.xml"))); + + // Our dummy floater.xml has a user localization (for "fr") but no + // English override. This is a case in which CURRENT_SKIN nonetheless + // returns paths from two different skins. + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "floater.xml"), + vec(list_of + ("install/skins/default/xui/en/floater.xml") + ("user/skins/default/xui/fr/floater.xml"))); + + // Our dummy newfile.xml has an English override but no user + // localization. This is another case in which CURRENT_SKIN + // nonetheless returns paths from two different skins. + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "newfile.xml"), + vec(list_of + ("user/skins/default/xui/en/newfile.xml") + ("install/skins/default/xui/fr/newfile.xml"))); + + ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), + vec(list_of + ("install/skins/default/html/en-us/welcome.html") + ("install/skins/default/html/fr/welcome.html"))); + + /*------------------------ "default", "zh" -------------------------*/ + lldir.setSkinFolder("default", "zh"); + // Because strings.xml has only a "fr" override but no "zh" override + // in any skin, the most localized version we can find is "en". + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), + vec(list_of("user/skins/default/xui/en/strings.xml"))); + + /*------------------------- "steam", "en" --------------------------*/ + lldir.setSkinFolder("steam", "en"); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS), + vec(list_of + ("install/skins/default/colors.xml") + ("install/skins/steam/colors.xml") + ("user/skins/default/colors.xml") + ("user/skins/steam/colors.xml"))); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_default.jpeg"), + vec(list_of("install/skins/default/textures/only_default.jpeg"))); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_steam.jpeg"), + vec(list_of("install/skins/steam/textures/only_steam.jpeg"))); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_user_default.jpeg"), + vec(list_of("user/skins/default/textures/only_user_default.jpeg"))); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_user_steam.jpeg"), + vec(list_of("user/skins/steam/textures/only_user_steam.jpeg"))); + + // CURRENT_SKIN + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), + vec(list_of("user/skins/steam/xui/en/strings.xml"))); + + // pass constraint=ALL_SKINS to request this filename in all relevant skins + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), + vec(list_of + ("install/skins/default/xui/en/strings.xml") + ("install/skins/steam/xui/en/strings.xml") + ("user/skins/default/xui/en/strings.xml") + ("user/skins/steam/xui/en/strings.xml"))); + + /*------------------------- "steam", "fr" --------------------------*/ + lldir.setSkinFolder("steam", "fr"); + + // pass CURRENT_SKIN to request only the most specialized files + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), + vec(list_of + ("user/skins/steam/xui/en/strings.xml") + ("user/skins/steam/xui/fr/strings.xml"))); + + // pass ALL_SKINS to request this filename in all relevant skins + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), + vec(list_of + ("install/skins/default/xui/en/strings.xml") + ("install/skins/default/xui/fr/strings.xml") + ("install/skins/steam/xui/en/strings.xml") + ("install/skins/steam/xui/fr/strings.xml") + ("user/skins/default/xui/en/strings.xml") + ("user/skins/default/xui/fr/strings.xml") + ("user/skins/steam/xui/en/strings.xml") + ("user/skins/steam/xui/fr/strings.xml"))); + } + + template<> template<> + void LLDirTest_object_t::test<7>() + { + set_test_name("add()"); + LLDir_Dummy lldir; + ensure_equals("both empty", lldir.add("", ""), ""); + ensure_equals("path empty", lldir.add("", "b"), "b"); + ensure_equals("name empty", lldir.add("a", ""), "a"); + ensure_equals("both simple", lldir.add("a", "b"), "a/b"); + ensure_equals("name leading slash", lldir.add("a", "/b"), "a/b"); + ensure_equals("path trailing slash", lldir.add("a/", "b"), "a/b"); + ensure_equals("both bring slashes", lldir.add("a/", "/b"), "a/b"); + } +} diff --git a/indra/llfilesystem/tests/lldiriterator_test.cpp b/indra/llfilesystem/tests/lldiriterator_test.cpp new file mode 100644 index 0000000000..a65e3dada5 --- /dev/null +++ b/indra/llfilesystem/tests/lldiriterator_test.cpp @@ -0,0 +1,65 @@ +/** + * @file lldiriterator_test.cpp + * @date 2011-06 + * @brief LLDirIterator test cases. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only., + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "lltut.h" +#include "../lldiriterator.h" + + +namespace tut +{ + + struct LLDirIteratorFixture + { + LLDirIteratorFixture() + { + } + }; + typedef test_group LLDirIteratorTest_factory; + typedef LLDirIteratorTest_factory::object LLDirIteratorTest_t; + LLDirIteratorTest_factory tf("LLDirIterator"); + + /* + CHOP-662 was originally introduced to deal with crashes deleting files from + a directory (VWR-25500). However, this introduced a crash looking for + old chat logs as the glob_to_regex function in lldiriterator wasn't escaping lots of regexp characters + */ + void test_chop_662(void) + { + // Check a selection of bad group names from the crash reports + LLDirIterator iter(".","+bad-group-name]+?\?-??.*"); + LLDirIterator iter1(".","))--@---bad-group-name2((?\?-??.*\\.txt"); + LLDirIterator iter2(".","__^v--x)Cuide d sua vida(x--v^__?\?-??.*"); + } + + template<> template<> + void LLDirIteratorTest_t::test<1>() + { + test_chop_662(); + } + +} diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index 1f6b981346..dc8e9f7c2f 100644 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -6,7 +6,7 @@ include(00-Common) include(LLCommon) include(LLImage) include(LLMath) -include(LLCache) +include(LLFileSystem) include(LLKDU) include(LLImageJ2COJ) include(ZLIB) @@ -17,7 +17,7 @@ include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLCOMMON_SYSTEM_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ) @@ -68,7 +68,7 @@ else (USE_KDU) endif (USE_KDU) target_link_libraries(llimage - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${JPEG_LIBRARIES} diff --git a/indra/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt index ba9f8af390..04975940aa 100644 --- a/indra/llinventory/CMakeLists.txt +++ b/indra/llinventory/CMakeLists.txt @@ -7,7 +7,7 @@ include(LLCommon) include(LLCoreHttp) include(LLMath) include(LLMessage) -include(LLCache) +include(LLFileSystem) include(LLXML) include_directories( @@ -81,7 +81,7 @@ if (LL_TESTS) LL_ADD_PROJECT_UNIT_TESTS(llinventory "${llinventory_TEST_SOURCE_FILES}") #set(TEST_DEBUG on) - set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLCACHE_LIBRARIES} ${LLCOREHTTP_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) + set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLFILESYSTEM_LIBRARIES} ${LLCOREHTTP_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) LL_ADD_INTEGRATION_TEST(inventorymisc "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llparcel "" "${test_libs}") endif (LL_TESTS) diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 66a7d3ea04..f0a1dfe940 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -9,7 +9,7 @@ include(LLCommon) include(LLCoreHttp) include(LLMath) include(LLMessage) -include(LLCache) +include(LLFileSystem) include(LLAddBuildTest) include(Python) include(Tut) @@ -23,7 +23,7 @@ include_directories( ${LLCOREHTTP_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${JSONCPP_INCLUDE_DIR} ) @@ -209,7 +209,7 @@ target_link_libraries( llmessage ${CURL_LIBRARIES} ${LLCOMMON_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLMATH_LIBRARIES} ${JSONCPP_LIBRARIES} ${OPENSSL_LIBRARIES} @@ -227,7 +227,7 @@ target_link_libraries( llmessage ${CURL_LIBRARIES} ${LLCOMMON_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLMATH_LIBRARIES} ${JSONCPP_LIBRARIES} ${OPENSSL_LIBRARIES} @@ -257,7 +257,7 @@ if (LL_TESTS) if (LINUX) set(test_libs ${WINDOWS_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLMATH_LIBRARIES} ${CURL_LIBRARIES} ${NGHTTP2_LIBRARIES} @@ -273,7 +273,7 @@ if (LINUX) else (LINUX) set(test_libs ${WINDOWS_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLMATH_LIBRARIES} ${CURL_LIBRARIES} ${NGHTTP2_LIBRARIES} diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 524e2a1729..baab09a104 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -11,7 +11,7 @@ include(LLMath) include(LLRender) include(LLWindow) include(LLXML) -include(LLCache) +include(LLFileSystem) include_directories( ${FREETYPE_INCLUDE_DIRS} @@ -19,10 +19,9 @@ include_directories( ${LLIMAGE_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} ) include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} @@ -103,9 +102,8 @@ if (BUILD_HEADLESS) ${LLIMAGE_LIBRARIES} ${LLMATH_LIBRARIES} ${LLRENDER_HEADLESS_LIBRARIES} - ${LLCACHE_LIBRARIES} ${LLXML_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLWINDOW_HEADLESS_LIBRARIES} ${OPENGL_HEADLESS_LIBRARIES}) @@ -125,7 +123,7 @@ target_link_libraries(llrender ${LLCOMMON_LIBRARIES} ${LLIMAGE_LIBRARIES} ${LLMATH_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLXML_LIBRARIES} ${LLWINDOW_LIBRARIES} ${FREETYPE_LIBRARIES} diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 02020b19c6..7401e6130a 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -13,7 +13,7 @@ include(LLCoreHttp) include(LLRender) include(LLWindow) include(LLCoreHttp) -include(LLCache) +include(LLFileSystem) include(LLXML) include_directories( @@ -25,7 +25,7 @@ include_directories( ${LLMESSAGE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${LIBS_PREBUILD_DIR}/include/hunspell ) @@ -283,7 +283,7 @@ target_link_libraries(llui ${LLINVENTORY_LIBRARIES} ${LLMESSAGE_LIBRARIES} ${LLCOREHTTP_LIBRARIES} - ${LLCACHE_LIBRARIES} # ugh, just for LLDir + ${LLFILESYSTEM_LIBRARIES} ${LLXUIXML_LIBRARIES} ${LLXML_LIBRARIES} ${LLMATH_LIBRARIES} diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 5603c2f322..70eb99c86c 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -16,7 +16,7 @@ include(LLCommon) include(LLImage) include(LLMath) include(LLRender) -include(LLCache) +include(LLFileSystem) include(LLWindow) include(LLXML) include(UI) @@ -26,7 +26,7 @@ include_directories( ${LLIMAGE_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ) @@ -72,7 +72,7 @@ if (LINUX) ${LLIMAGE_LIBRARIES} ${LLMATH_LIBRARIES} ${LLRENDER_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLWINDOW_LIBRARIES} ${LLXML_LIBRARIES} ${UI_LIBRARIES} # for GTK @@ -95,7 +95,7 @@ if (LINUX) ${LLIMAGE_LIBRARIES} ${LLMATH_LIBRARIES} ${LLRENDER_HEADLESS_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLWINDOW_HEADLESS_LIBRARIES} ${LLXML_LIBRARIES} fontconfig # For FCInit and other FC* functions. diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt index e2c6026496..3a7a54e51d 100644 --- a/indra/llxml/CMakeLists.txt +++ b/indra/llxml/CMakeLists.txt @@ -5,13 +5,13 @@ project(llxml) include(00-Common) include(LLCommon) include(LLMath) -include(LLCache) +include(LLFileSystem) include(LLXML) include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ) include_directories( ${LLCOMMON_SYSTEM_INCLUDE_DIRS} @@ -42,7 +42,7 @@ add_library (llxml ${llxml_SOURCE_FILES}) # Libraries on which this library depends, needed for Linux builds # Sort by high-level to low-level target_link_libraries( llxml - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${EXPAT_LIBRARIES} diff --git a/indra/mac_crash_logger/CMakeLists.txt b/indra/mac_crash_logger/CMakeLists.txt index 4a10076e6e..75621d7b75 100644 --- a/indra/mac_crash_logger/CMakeLists.txt +++ b/indra/mac_crash_logger/CMakeLists.txt @@ -8,7 +8,7 @@ include(LLCoreHttp) include(LLCrashLogger) include(LLMath) include(LLMessage) -include(LLCache) +include(LLFilesystem) include(LLXML) include(Linking) include(LLSharedLibs) @@ -19,7 +19,7 @@ include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLCRASHLOGGER_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ) include_directories(SYSTEM @@ -68,7 +68,7 @@ find_library(COCOA_LIBRARY Cocoa) target_link_libraries(mac-crash-logger ${LLCRASHLOGGER_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${COCOA_LIBRARIES} ${LLXML_LIBRARIES} ${LLMESSAGE_LIBRARIES} diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ccf7ad675f..cda2672e12 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -39,7 +39,7 @@ include(LLPlugin) include(LLPrimitive) include(LLRender) include(LLUI) -include(LLCache) +include(LLFileSystem) include(LLWindow) include(LLXML) include(NDOF) @@ -84,7 +84,7 @@ include_directories( ${LLPRIMITIVE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLUI_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${LLLOGIN_INCLUDE_DIRS} @@ -1995,7 +1995,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLRENDER_LIBRARIES} ${FREETYPE_LIBRARIES} ${LLUI_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLWINDOW_LIBRARIES} ${LLXML_LIBRARIES} ${LLMATH_LIBRARIES} @@ -2467,7 +2467,7 @@ if (LL_TESTS) set(test_libs ${LLMESSAGE_LIBRARIES} ${WINDOWS_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${GOOGLEMOCK_LIBRARIES} @@ -2482,7 +2482,7 @@ if (LL_TESTS) set(test_libs ${WINDOWS_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${LLMESSAGE_LIBRARIES} diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index f8e701794c..b3bff3611a 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -8,12 +8,11 @@ include(LLCoreHttp) include(LLInventory) include(LLMath) include(LLMessage) -include(LLCache) +include(LLFileSystem) include(LLXML) include(Linking) include(Tut) include(LLAddBuildTest) - include(GoogleMock) include_directories( @@ -23,7 +22,7 @@ include_directories( ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLINVENTORY_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ${GOOGLEMOCK_INCLUDE_DIRS} @@ -89,7 +88,7 @@ target_link_libraries(lltest ${LLINVENTORY_LIBRARIES} ${LLMESSAGE_LIBRARIES} ${LLMATH_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLXML_LIBRARIES} ${LSCRIPT_LIBRARIES} ${LLCOMMON_LIBRARIES} diff --git a/indra/win_crash_logger/CMakeLists.txt b/indra/win_crash_logger/CMakeLists.txt index 811ec00a3d..1b187d624a 100644 --- a/indra/win_crash_logger/CMakeLists.txt +++ b/indra/win_crash_logger/CMakeLists.txt @@ -8,7 +8,7 @@ include(LLCoreHttp) include(LLCrashLogger) include(LLMath) include(LLMessage) -include(LLCache) +include(LLFileSystem) include(LLWindow) include(LLXML) include(Linking) @@ -23,7 +23,7 @@ include_directories( ${LLMATH_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLCACHE_INCLUDE_DIRS} + ${LLFILESYSTEM_INCLUDE_DIRS} ${BREAKPAD_INCLUDE_DIRECTORIES} ) include_directories(SYSTEM @@ -76,7 +76,7 @@ target_link_libraries(windows-crash-logger ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES} ${LLCRASHLOGGER_LIBRARIES} ${LLWINDOW_LIBRARIES} - ${LLCACHE_LIBRARIES} + ${LLFILESYSTEM_LIBRARIES} ${LLXML_LIBRARIES} ${LLMESSAGE_LIBRARIES} ${LLMATH_LIBRARIES} -- cgit v1.3 From 6be1f88a5ef99e1e40bb5701a250ba0728f56005 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 24 Sep 2020 14:45:39 -0700 Subject: Complete the change from lldiskcache -> llfilesystem and then addition of new lldiskcache implementation --- indra/llappearance/lltexlayer.cpp | 1 - indra/llaudio/llaudiodecodemgr.cpp | 14 +- indra/llaudio/llaudioengine.cpp | 4 +- indra/llcharacter/llkeyframemotion.cpp | 6 +- indra/llfilesystem/CMakeLists.txt | 3 +- indra/llfilesystem/lldiskcache.cpp | 773 ++++++++++++++++++++++++++++++ indra/llfilesystem/lldiskcache.h | 130 +++++ indra/llfilesystem/llfilesystem.cpp | 79 ++- indra/llfilesystem/llfilesystem.h | 19 +- indra/llmessage/llassetstorage.cpp | 28 +- indra/llmessage/llcorehttputil.cpp | 4 +- indra/llmessage/lltransfersourceasset.cpp | 6 +- indra/llmessage/lltransfersourceasset.h | 2 +- indra/llmessage/lltransfertargetvfile.cpp | 8 +- indra/llmessage/lltransfertargetvfile.h | 4 +- indra/llmessage/llxfer_vfile.cpp | 22 +- indra/llmessage/llxfer_vfile.h | 4 +- indra/llui/llviewereventrecorder.h | 1 - indra/newview/llappviewer.cpp | 6 +- indra/newview/llcompilequeue.cpp | 2 +- indra/newview/llfloaterauction.cpp | 6 +- indra/newview/llfloaterbvhpreview.cpp | 4 +- indra/newview/llfloatermodelpreview.cpp | 2 +- indra/newview/llfloaterregioninfo.cpp | 4 +- indra/newview/llfloaterreporter.cpp | 4 +- indra/newview/llfloatertos.cpp | 2 +- indra/newview/llgesturemgr.cpp | 4 +- indra/newview/lllandmarklist.cpp | 4 +- indra/newview/llmeshrepository.cpp | 22 +- indra/newview/lloutfitgallery.cpp | 2 +- indra/newview/llpostcard.cpp | 2 +- indra/newview/llpreviewgesture.cpp | 6 +- indra/newview/llpreviewnotecard.cpp | 10 +- indra/newview/llpreviewscript.cpp | 6 +- indra/newview/llsettingsvo.cpp | 4 +- indra/newview/llsnapshotlivepreview.cpp | 4 +- indra/newview/llviewerassetstorage.cpp | 12 +- indra/newview/llviewerassetstorage.h | 2 +- indra/newview/llviewerassetupload.cpp | 8 +- indra/newview/llviewermenufile.cpp | 1 - indra/newview/llviewermessage.cpp | 4 +- indra/newview/llviewerstats.cpp | 1 - indra/newview/llviewertexlayer.cpp | 1 - indra/newview/llviewertexture.cpp | 1 - indra/newview/llviewertexture.h | 2 +- indra/newview/llviewertexturelist.cpp | 2 +- 46 files changed, 1068 insertions(+), 168 deletions(-) create mode 100644 indra/llfilesystem/lldiskcache.cpp create mode 100644 indra/llfilesystem/lldiskcache.h (limited to 'indra/llui') diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 7360c1acd7..1348fb0763 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -33,7 +33,6 @@ #include "llimagej2c.h" #include "llimagetga.h" #include "lldir.h" -#include "lldiskcache.h" #include "lltexlayerparams.h" #include "lltexturemanagerbridge.h" #include "lllocaltextureobject.h" diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index fcffea42a4..ff0aa6e76e 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -29,7 +29,7 @@ #include "llaudioengine.h" #include "lllfsthread.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llstring.h" #include "lldir.h" #include "llendianswizzle.h" @@ -93,14 +93,14 @@ protected: std::string mOutFilename; LLLFSThread::handle_t mFileHandle; - LLDiskCache *mInFilep; + LLFileSystem *mInFilep; OggVorbis_File mVF; S32 mCurrentSection; }; size_t cache_read(void *ptr, size_t size, size_t nmemb, void *datasource) { - LLDiskCache *file = (LLDiskCache *)datasource; + LLFileSystem *file = (LLFileSystem *)datasource; if (file->read((U8*)ptr, (S32)(size * nmemb))) /*Flawfinder: ignore*/ { @@ -115,7 +115,7 @@ size_t cache_read(void *ptr, size_t size, size_t nmemb, void *datasource) S32 cache_seek(void *datasource, ogg_int64_t offset, S32 whence) { - LLDiskCache *file = (LLDiskCache *)datasource; + LLFileSystem *file = (LLFileSystem *)datasource; // cache has 31-bit files if (offset > S32_MAX) @@ -151,14 +151,14 @@ S32 cache_seek(void *datasource, ogg_int64_t offset, S32 whence) S32 cache_close (void *datasource) { - LLDiskCache *file = (LLDiskCache *)datasource; + LLFileSystem *file = (LLFileSystem *)datasource; delete file; return 0; } long cache_tell (void *datasource) { - LLDiskCache *file = (LLDiskCache *)datasource; + LLFileSystem *file = (LLFileSystem *)datasource; return file->tell(); } @@ -198,7 +198,7 @@ BOOL LLVorbisDecodeState::initDecode() LL_DEBUGS("AudioEngine") << "Initing decode from vfile: " << mUUID << LL_ENDL; - mInFilep = new LLDiskCache(mUUID, LLAssetType::AT_SOUND); + mInFilep = new LLFileSystem(mUUID, LLAssetType::AT_SOUND); if (!mInFilep || !mInFilep->getSize()) { LL_WARNS("AudioEngine") << "unable to open vorbis source vfile for reading" << LL_ENDL; diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 9dd752f492..d35f249973 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -35,7 +35,7 @@ #include "sound_ids.h" // temporary hack for min/max distances -#include "lldiskcache.h" +#include "llfilesystem.h" #include "lldir.h" #include "llaudiodecodemgr.h" #include "llassetstorage.h" @@ -1015,7 +1015,7 @@ bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid) bool LLAudioEngine::hasLocalFile(const LLUUID &uuid) { // See if it's in the cache. - bool have_local = LLDiskCache::getExists(uuid, LLAssetType::AT_SOUND); + bool have_local = LLFileSystem::getExists(uuid, LLAssetType::AT_SOUND); LL_DEBUGS("AudioEngine") << "sound uuid " << uuid << " exists in cache" << LL_ENDL; return have_local; } diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index d1ac336fc1..fe9de30f0a 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -39,9 +39,9 @@ #include "llendianswizzle.h" #include "llkeyframemotion.h" #include "llquantize.h" -#include "lldiskcache.h" #include "m3math.h" #include "message.h" +#include "llfilesystem.h" //----------------------------------------------------------------------------- // Static Definitions @@ -559,7 +559,7 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact S32 anim_file_size; BOOL success = FALSE; - LLDiskCache* anim_file = new LLDiskCache(mID, LLAssetType::AT_ANIMATION); + LLFileSystem* anim_file = new LLFileSystem(mID, LLAssetType::AT_ANIMATION); if (!anim_file || !anim_file->getSize()) { delete anim_file; @@ -2324,7 +2324,7 @@ void LLKeyframeMotion::onLoadComplete(const LLUUID& asset_uuid, // asset already loaded return; } - LLDiskCache file(asset_uuid, type, LLDiskCache::READ); + LLFileSystem file(asset_uuid, type, LLFileSystem::READ); S32 size = file.getSize(); U8* buffer = new U8[size]; diff --git a/indra/llfilesystem/CMakeLists.txt b/indra/llfilesystem/CMakeLists.txt index 306b483097..d1dece5bba 100644 --- a/indra/llfilesystem/CMakeLists.txt +++ b/indra/llfilesystem/CMakeLists.txt @@ -18,16 +18,17 @@ set(llfilesystem_SOURCE_FILES lldiriterator.cpp lllfsthread.cpp lldiskcache.cpp + llfilesystem.cpp ) set(llfilesystem_HEADER_FILES CMakeLists.txt - lldir.h lldirguard.h lldiriterator.h lllfsthread.h lldiskcache.h + llfilesystem.h ) if (DARWIN) diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp new file mode 100644 index 0000000000..72982db069 --- /dev/null +++ b/indra/llfilesystem/lldiskcache.cpp @@ -0,0 +1,773 @@ +/** + * @file lldiskcache.cpp + * @brief The SQLite based disk cache implementation. + * @Note Eventually, this component might split into an interface + * file and multiple implemtations but for now, this is the + * only one so I think it's okay to combine everything. + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if (defined(LL_WINDOWS) || defined(LL_LINUX) || defined(LL_DARWIN)) +#include "linden_common.h" +#endif + +#include "lldiskcache.h" + +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +// +llDiskCache::llDiskCache() : + mDataStorePath("") +{ +} + +llDiskCache::~llDiskCache() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Opens the database - typically done when the application starts +// and is complementary to close() which is called when the application +// is finisahed and exits. +// Pass in the folder and filename of the SQLite database you want to +// use or create (file doesn't have to exist but the folder must) +// Returns true or false and writes a message to console on error +bool llDiskCache::open(const std::string db_folder, const std::string db_filename) +{ + mDataStorePath = db_folder; + std::string db_pathname = makeFullPath(db_filename); + + // simple flags for the moment - these will likely be extended + // later on to support the SQLite mutex model for reading/writing + // simultaneously - perhaps when we look at supporting textures too + int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + + if (sqlite3_open_v2( + db_pathname.c_str(), + &mDb, + flags, + nullptr // Name of VFS module to use + ) != SQLITE_OK) + { + printError(__FUNCDNAME__ , "open_v2", true); + close(); + return false; + } + + // I elected to store the code that generates the statement + // in sepsrate functions throughout - this seemed like a cleaner + // approach than having hundreds of stmt << "REPLACE AS" lines + // interspersed in the logic code. They are all prefixed with + // 'sqlCompose' and followed by a short description. + const std::string stmt = sqlComposeCreateTable(); + if (! sqliteExec(stmt, __FUNCDNAME__ )) + { + // Not sure if we need close here - if open fails, then we + // perhaps don't need to close it - TODO: look in SQLite docs + close(); + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Determines if an entry exists. +// Pass in the id and a variable that will indicate existance +// Returns true/false if function succeeded and the boolean +// you pass in will be set to true/false if entry exists or not +bool llDiskCache::exists(const std::string id, bool& exists) +{ + if (!mDb) + { + printError(__FUNCDNAME__ , "mDb is invalid", false); + return false; + } + + if (id.empty()) + { + printError(__FUNCDNAME__ , "id is empty", false); + return false; + } + + // As well as the separate function to compose the SQL statement, + // worth pointing out that the code to 'prepare' and 'step' the + // SQLite "prepared statement" has been factored out into its own + // function and used in several other functions. + const std::string stmt = sqlComposeExists(id); + sqlite3_stmt* prepared_statement = sqlitePrepareStep(__FUNCDNAME__ , stmt, SQLITE_ROW); + if (! prepared_statement) + { + return false; + } + + int result_column_index = 0; + int result_count = sqlite3_column_int(prepared_statement, result_column_index); + if (sqlite3_finalize(prepared_statement) != SQLITE_OK) + { + printError(__FUNCDNAME__ , "sqlite3_finalize()", true); + return false; + } + + // given the uniqueness of the ID, this can only ever be + // either 1 or 0 so this might be a bit confusing + exists = result_count > 0 ? true : false; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Given an id (likely a UUID + decoration but can be any string), a +// pointer to a blob of binary data along with its length, write the +// entry to the cache +// Returns true/false for success/failure +bool llDiskCache::put(const std::string id, + char* binary_data, + int binary_data_size) +{ + if (!mDb) + { + printError(__FUNCDNAME__ , "mDb is invalid", false); + return false; + } + + if (id.empty()) + { + printError(__FUNCDNAME__ , "id is empty", false); + return false; + } + + // < 0 is obvious but we assert the data must be at least 1 byte long + if (binary_data_size <= 0) + { + printError(__FUNCDNAME__ , "size of binary file to write is invalid", false); + return false; + } + + // we generate a unique filename for the actual data itself + // which is stored on disk directly and not in the database. + // TODO: consider making the filename more like the ID passed in + // although the problem with that is we would have to parse the id + // to remove invalid filename chars, consider length etc. As it + // stands, we can write a simple SQL statement to return the filename + // given the ID. + const std::string filename = makeUniqueFilename(); + const std::string filepath = makeFullPath(filename); + std::ofstream file(filepath, std::ios::out | std::ios::binary); + if (! file.is_open()) + { + std::ostringstream error; + error << "Unable to open " << filepath << " for writing"; + printError(__FUNCDNAME__ , error.str(), false); + return false; + } + + file.write((char*)binary_data, binary_data_size); + file.close(); + + // I think is a catchall "wasn't able to write the file to disk" + // conditional but should revisit when we hook this up to viewer + // code to make sure - we never want to write bad/no data to the + // disk and not indicate something has gone wrong + if (file.bad()) + { + std::ostringstream error; + error << "Unable to write " << binary_data_size; + error << " bytes to " << filepath; + printError(__FUNCDNAME__ , error.str(), false); + + return false; + } + + // this is where the filename/size is written to the database along + // with the current date/time for the created/last access times + const std::string stmt = sqlComposePut(id, filename, binary_data_size); + if (! sqlitePrepareStep(__FUNCDNAME__ , stmt, SQLITE_DONE)) + { + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Given an id (likely a UUID + decoration but can be any string), the +// address of a pointer that will be used to allocate memory and a +// varialble that will contain the length of the data, get an item from +// the cache. Note that the memory buffer returned belongs to the calling +// function and it is its responsiblity to clean it up when it's no +// longer needed. +// Returns true/false for success/failure +const bool llDiskCache::get(const std::string id, + char** mem_buffer, + int& mem_buffer_size) +{ + // Check if the entry exists first to avoid dealing with a bunch + // of conditions that look like failure but aren't in the main code. + // Note exists() is a public method and also tests for mDB and id + // being valid so we can safely put this about the same tests + // in this function + bool get_exists = false; + if (! exists(id, get_exists)) + { + return false; + } + if (! get_exists) + { + return false; + } + + if (!mDb) + { + printError(__FUNCDNAME__ , "mDb is invalid", false); + return false; + } + + if (id.empty()) + { + printError(__FUNCDNAME__ , "id is empty", false); + return false; + } + + const std::string stmt_select = sqlComposeGetSelect(id); + sqlite3_stmt* prepared_statement = sqlitePrepareStep(__FUNCDNAME__ , stmt_select, SQLITE_ROW); + if (! prepared_statement) + { + return false; + } + + int result_column_index = 0; + const unsigned char* text = sqlite3_column_text(prepared_statement, result_column_index); + if (text == nullptr) + { + printError(__FUNCDNAME__ , "filename is nullptr", true); + return false; + } + const std::string filename = std::string(reinterpret_cast(text)); + const std::string filepath = makeFullPath(filename); + + result_column_index = 1; + int filesize_db = sqlite3_column_int(prepared_statement, result_column_index); + if (filesize_db <= 0) + { + printError(__FUNCDNAME__ , "filesize is invalid", true); + return false; + } + + if (sqlite3_finalize(prepared_statement) != SQLITE_OK) + { + printError(__FUNCDNAME__ , "sqlite3_finalize()", true); + return false; + } + + // Now we have the fiename, we can read the file from disk + std::ifstream file(filepath, std::ios::in | std::ios::binary | std::ios::ate); + if (! file.is_open()) + { + std::ostringstream error; + error << "Unable to open " << filepath << " for reading"; + printError(__FUNCDNAME__ , error.str(), false); + return false; + } + + // we get the expected filesize from the database but we can also + // get it (easily) when we read the file from the disk. We compare + // the two and return false if they don't match + std::streampos filesize_file = file.tellg(); + if (filesize_db != filesize_file) + { + std::ostringstream error; + error << "File size from DB (" << filesize_db << ")"; + error << " and "; + error << "file size from file (" << filesize_file << ")"; + error << " in file " << filepath << " are different"; + printError(__FUNCDNAME__ , error.str(), false); + + return false; + } + + // doest matter if we choose DB or file version - they must be + // identical if we get this far - just used for clarity + int filesize = filesize_db; + + // allocate a block of memory that we pass back for the calling + // function to use then delete when it's no longer needed + *mem_buffer = new char[filesize]; + mem_buffer_size = filesize; + + file.seekg(0, std::ios::beg); + file.read(*mem_buffer, filesize); + file.close(); + + if (file.bad()) + { + std::ostringstream error; + error << "Unable to read " << filesize; + error << " bytes from " << filepath; + printError(__FUNCDNAME__ , error.str(), false); + + return false; + } + + // here we update the count of times the file is accessed so + // we can keep track of how many times it's been requested. + // This will be useful for metrics and perhaps determining + // if a file should not be purged even though its age + // might suggest that it should. + // In addition, this is where the time of last access is updated + // in the database and that us used to determine what is purged + // in an LRU fashion when the purge function is called. + const std::string stmt_update = sqlComposeGetUpdate(id); + if (! sqliteExec(stmt_update, __FUNCDNAME__ )) + { + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Purges the database of older entries using an LRU approach. +// Pass in the number of entries to retain. +// This is called now after open to "clean up" the cache when the +// application starts. +// TODO: IMPORTANT: compose a list of files that will be deleted +// and delete them from disk too - not just from the DB +bool llDiskCache::purge(int num_entries) +{ + if (num_entries < 0) + { + printError(__FUNCDNAME__ , "number of entries to purge is invalid", false); + return false; + } + + // find the rows affected and get the filenames for them +//swww + + // delete oldest entries leaving the correct number in place + const std::string stmt = sqlComposePurge(num_entries); + if (! sqliteExec(stmt, __FUNCDNAME__ )) + { + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Call at application shutdown +void llDiskCache::close() +{ + sqlite3_close(mDb); +} + +/////////////////////////////////////////////////////////////////////////////// +// Determine the version of SQLite in use +// TODO: make this a static so we can get to it from the Viewer About +// box without instantiating the whole thing. +const std::string llDiskCache::dbVersion() +{ + std::ostringstream version; + + version << sqlite3_libversion(); + + return version.str(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Given an id, return the matching filename +const std::string llDiskCache::getFilenameById(const std::string id) +{ + // TODO: + return std::string(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Given an id, return the number of times that entry has been +// accessed from the cache +const int llDiskCache::getAccessCountById(const std::string id) +{ + // TODO: + return -1; +} + +/////////////////////////////////////////////////////////////////////////////// +// Return the number of entries currently in the cache as well as +// the maximum possible entries. +void llDiskCache::getNumEntries(int& num_entries, int& max_entries) +{ + num_entries = -1; + max_entries = -1; +} + +/////////////////////////////////////////////////////////////////////////////// +// Wraps the sqlite3_exec(..) used in many places +bool llDiskCache::sqliteExec(const std::string stmt, + const std::string funcname) +{ + if (sqlite3_exec( + mDb, + stmt.c_str(), + nullptr, // Callback function (unused) + nullptr, // 1st argument to callback (unused) + nullptr // Error msg written here (unused) + ) != SQLITE_OK) + { + printError(funcname, "sqlite3_exec", true); + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Wraps the sqlite3_prepare_v2 and sqlite3_step calls used in many places +sqlite3_stmt* llDiskCache::sqlitePrepareStep(const std::string funcname, + const std::string stmt, + int sqlite_success_condition) +{ + sqlite3_stmt* prepared_statement; + + if (sqlite3_prepare_v2( + mDb, + stmt.c_str(), + -1, // Maximum length of zSql in bytes. + &prepared_statement, + 0 // OUT: Pointer to unused portion of zSql + ) != SQLITE_OK) + { + printError(funcname, "sqlite3_prepare_v2", true); + return nullptr; + } + + if (sqlite3_step(prepared_statement) != sqlite_success_condition) + { + printError(funcname, "sqlite3_step", true); + sqlite3_finalize(prepared_statement); + return nullptr; + } + return prepared_statement; +} + +/////////////////////////////////////////////////////////////////////////////// +// When an "error" occurss - e.g. database cannot be found, file cannot be +// written, invalid argument passed into a function etc. a message is +// written to stderr that should end up in the viewer log +// TODO: Set the verbosity using the usual Viewer mechanism +void llDiskCache::printError(const std::string funcname, + const std::string desc, + bool is_sqlite_err) +{ + std::ostringstream err_msg; + + err_msg << "llDiskCache error in "; + err_msg << __FUNCDNAME__ << "(...) "; + err_msg << desc; + + if (is_sqlite_err) + { + err_msg << " - "; + err_msg << std::string(sqlite3_errmsg(mDb)); + } + + // TODO: set via viewer verbosity level + const int verbosity = 1; + if (verbosity > 0) + { + std::cerr << err_msg.str() << std::endl; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// wrapper for SQLite code to begin an SQL transaction - not used yet but +// it will be eventually +bool llDiskCache::beginTransaction() +{ + const std::string stmt("BEGIN TRANSACTION"); + if (! sqliteExec(stmt, __FUNCDNAME__ )) + { + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// wrapper for SQLite code to end an SQL transaction - not used yet but +// it will be eventually +bool llDiskCache::endTransaction() +{ + const std::string stmt("COMMIT"); + if (! sqliteExec(stmt, __FUNCDNAME__ )) + { + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Build a unique filename that will be used to store the actual file +// on disk (as opposed to the meta data in the database) +// TODO: I think this needs more work once we move it to the viewer +// and espcially to make it cross platform - see 'std::tmpnam' +// depreciation comments in compiler output for example +std::string llDiskCache::makeUniqueFilename() +{ + // TODO: replace with boost - this is marked as deprecated? + std::string base = std::tmpnam(nullptr); + + // C++11 random number generation!!! + static std::random_device dev; + static std::mt19937 rng(dev()); + std::uniform_int_distribution dist(100000, 999999); + + // currently the tmp filename from std::tmpnam() on macOS + // is of the form `/tmp/foo/bar.12345 and the following code + // strips all the preceding dirs - we likely want a more + // robust (and cross platform solution) when we move to the + // viewer code + std::size_t found = base.rfind(systemSeparator()); + if (found != std::string::npos && found < base.size() - 2) + { + base = base.substr(found + 1); + } + else + { + base = ""; + } + + // we mix in a random number for some more entropy.. + // (i know, i know...) + std::ostringstream unique_filename; + unique_filename << base; + unique_filename << "."; + unique_filename << dist(rng); + + return unique_filename.str(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Return system file/path separator - likely replaced by the version +// in the viewer +const std::string llDiskCache::systemSeparator() +{ +// TODO: replace in viewer with relevant call +#ifdef _WIN32 + return "\\"; +#else + return "/"; +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// Given a filename, compose a full path based on the path name passed +// in when the database was opened and the separator in play. +const std::string llDiskCache::makeFullPath(const std::string filename) +{ + std::string pathname = mDataStorePath + systemSeparator() + filename; + + return pathname; +} + +/////////////////////////////////////////////////////////////////////////////// +// +const std::string llDiskCache::sqlComposeCreateTable() +{ + std::ostringstream stmt; + stmt << "CREATE TABLE IF NOT EXISTS "; + stmt << mTableName; + stmt << "("; + stmt << mIdFieldName; + stmt << " TEXT PRIMARY KEY, "; + stmt << mFilenameFieldName; + stmt << " TEXT, "; + stmt << mFilesizeFieldName; + stmt << " INTEGER DEFAULT 0, "; + stmt << mInsertionDateTimeFieldName; + stmt << " TEXT, "; + stmt << mLastAccessDateTimeFieldName; + stmt << " TEXT, "; + stmt << mAccessCountFieldName; + stmt << " INTEGER DEFAULT 0"; + stmt << ")"; + +#ifdef SHOW_STATEMENTS + std::cout << stmt.str() << std::endl; +#endif + + return stmt.str(); +} + +/////////////////////////////////////////////////////////////////////////////// +// +const std::string llDiskCache::sqlComposeExists(const std::string id) +{ + std::ostringstream stmt; + stmt << "SELECT COUNT(*) FROM "; + stmt << mTableName; + stmt << " WHERE "; + stmt << mIdFieldName; + stmt << "='"; + stmt << id; + stmt << "'"; + +#ifdef SHOW_STATEMENTS + std::cout << stmt.str() << std::endl; +#endif + + return stmt.str(); +} + +/////////////////////////////////////////////////////////////////////////////// +// SQL statement to write an entry to the DB +// Saves id, filename (generated), file size and create/last access date +const std::string llDiskCache::sqlComposePut(const std::string id, + const std::string filename, + int binary_data_size) +{ + std::ostringstream stmt; + stmt << "REPLACE INTO "; + stmt << mTableName; + stmt << "("; + stmt << mIdFieldName; + stmt << ","; + stmt << mFilenameFieldName; + stmt << ","; + stmt << mFilesizeFieldName; + stmt << ","; + stmt << mInsertionDateTimeFieldName; + stmt << ","; + stmt << mLastAccessDateTimeFieldName; + stmt << ") "; + stmt << "VALUES("; + stmt << "'"; + stmt << id; + stmt << "', "; + stmt << "'"; + stmt << filename; + stmt << "', "; + stmt << binary_data_size; + stmt << ", "; + stmt << "strftime('%Y-%m-%d %H:%M:%f', 'now')"; + stmt << ", "; + stmt << "strftime('%Y-%m-%d %H:%M:%f', 'now')"; + stmt << ")"; + +#ifdef SHOW_STATEMENTS + std::cout << stmt.str() << std::endl; +#endif + + return stmt.str(); +} + +/////////////////////////////////////////////////////////////////////////////// +// SQL statement used in get() to look up the filename and file size +const std::string llDiskCache::sqlComposeGetSelect(const std::string id) +{ + std::ostringstream stmt; + stmt << "SELECT "; + stmt << mFilenameFieldName; + stmt << ", "; + stmt << mFilesizeFieldName; + stmt << " FROM "; + stmt << mTableName; + stmt << " WHERE "; + stmt << mIdFieldName; + stmt << "='"; + stmt << id; + stmt << "'"; + +#ifdef SHOW_STATEMENTS + std::cout << stmt.str() << std::endl; +#endif + + return stmt.str(); +} + +/////////////////////////////////////////////////////////////////////////////// +// SQL statement to update the date/time of last access as well as the +// count of number of times the file has been accessed. +// Note: the more accurate representation of date/time is used to +// ensure ms accuracy vs the standard INTEGER days since epoch approach +const std::string llDiskCache::sqlComposeGetUpdate(const std::string id) +{ + std::ostringstream stmt; + stmt << "UPDATE "; + stmt << mTableName; + stmt << " SET "; + stmt << mAccessCountFieldName; + stmt << "="; + stmt << mAccessCountFieldName; + stmt << "+1"; + stmt << ", "; + stmt << mLastAccessDateTimeFieldName; + stmt << "="; + stmt << "strftime('%Y-%m-%d %H:%M:%f', 'now')"; + stmt << " WHERE "; + stmt << mIdFieldName; + stmt << "='"; + stmt << id; + stmt << "'"; + +#ifdef SHOW_STATEMENTS + std::cout << stmt.str() << std::endl; +#endif + + return stmt.str(); +} + +/////////////////////////////////////////////////////////////////////////////// +// SQL statement to remove items from the database that are older +// than the newest num_elements entries +const std::string llDiskCache::sqlComposePurge(int num_entries) +{ + std::ostringstream stmt; + stmt << "DELETE FROM "; + stmt << mTableName; + stmt << " WHERE "; + stmt << mLastAccessDateTimeFieldName; + stmt << " NOT IN "; + stmt << "("; + stmt << "SELECT "; + stmt << mLastAccessDateTimeFieldName; + stmt << " FROM "; + stmt << mTableName; + stmt << " ORDER BY "; + stmt << mLastAccessDateTimeFieldName; + stmt << " DESC"; + stmt << " LIMIT "; + stmt << num_entries; + stmt << ")"; + +//#ifdef SHOW_STATEMENTS + std::cout << stmt.str() << std::endl; +//#endif + + return stmt.str(); +} diff --git a/indra/llfilesystem/lldiskcache.h b/indra/llfilesystem/lldiskcache.h new file mode 100644 index 0000000000..39b8f7ef48 --- /dev/null +++ b/indra/llfilesystem/lldiskcache.h @@ -0,0 +1,130 @@ +/** + * @file lldiskcache.h + * @brief Declaration SQLite meta data / file storage API + * @brief Declaration of the generic disk cache interface + as well the SQLite header/implementation. + * @Note Eventually, this component might split into an interface + * file and multiple implemtations but for now, this is the + * only one so I think it's okay to combine everything. + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef _LLDISKCACHE +#define _LLDISKCACHE + +#include +#include + +#include "sqlite3.h" + +// Enable this line to display each SQL statement when it is executed +// It can lead to a lot of spam but useful for debugging +//#define SHOW_STATEMENTS + +// I toyed with the idea of a variety of approaches and thought have +// an abstract base class with which to hang different implementations +// off was a good idea but I think we settled on a single approach +// so I will likely remove this level of indirection if not other +// interesting implementation ideas present themselves. +class llDiskCacheBase +{ + public: + llDiskCacheBase() {}; + virtual ~llDiskCacheBase() {}; + virtual bool open(const std::string db_folder, + const std::string db_filename) = 0; + virtual bool exists(const std::string id, bool& exists) = 0; + virtual bool put(const std::string id, + char* binary_data, + int binary_data_size) = 0; + virtual const bool get(const std::string id, + char** mem_buffer, + int& mem_buffer_size) = 0; + virtual bool purge(int num_entries) = 0; + virtual void close() = 0; + virtual const std::string dbVersion() = 0; + virtual const std::string getFilenameById(const std::string id) = 0; + virtual const int getAccessCountById(const std::string id) = 0; + virtual void getNumEntries(int& num_entries, int& max_entries) = 0; +}; + +// implementation for the SQLite/disk blended case +// see source file for detailed comments +class llDiskCache : + public llDiskCacheBase +{ + public: + llDiskCache(); + virtual ~llDiskCache(); + virtual bool open(const std::string db_folder, + const std::string db_filename) override; + virtual bool exists(const std::string id, bool& exists) override; + virtual bool put(const std::string id, + char* binary_data, + int binary_data_size) override; + virtual const bool get(const std::string id, + char** mem_buffer, + int& mem_buffer_size) override; + virtual bool purge(int num_entries) override; + virtual void close() override; + virtual const std::string dbVersion() override; + virtual const std::string getFilenameById(const std::string id) override; + virtual const int getAccessCountById(const std::string id) override; + virtual void getNumEntries(int& num_entries, int& max_entries) override; + + private: + sqlite3* mDb; + std::string mDataStorePath; + const std::string mTableName = "lldiskcache"; + const std::string mIdFieldName = "id"; + const std::string mFilenameFieldName = "filename"; + const std::string mFilesizeFieldName = "filesize"; + const std::string mInsertionDateTimeFieldName = "insert_datetime"; + const std::string mLastAccessDateTimeFieldName = "last_access_datetime"; + const std::string mAccessCountFieldName = "access_count"; + + private: + void printError(const std::string funcname, + const std::string desc, + bool is_sqlite_err); + bool beginTransaction(); + bool endTransaction(); + std::string makeUniqueFilename(); + const std::string systemSeparator(); + const std::string makeFullPath(const std::string filename); + bool sqliteExec(const std::string stmt, + const std::string funcname); + sqlite3_stmt* sqlitePrepareStep(const std::string funcname, + const std::string stmt, + int sqlite_success_condition); + const std::string sqlComposeCreateTable(); + const std::string sqlComposeExists(const std::string id); + const std::string sqlComposePut(const std::string id, + const std::string filename, + int binary_data_size); + const std::string sqlComposeGetSelect(const std::string id); + const std::string sqlComposeGetUpdate(const std::string id); + const std::string sqlComposePurge(int num_entries); +}; + +#endif // _LLDISKCACHE diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp index af93049e07..f0037c9a22 100644 --- a/indra/llfilesystem/llfilesystem.cpp +++ b/indra/llfilesystem/llfilesystem.cpp @@ -1,6 +1,9 @@ /** - * @file lldiskcache.cpp - * @brief Implementation of virtual file + * @file filesystem.h + * @brief Simulate local file system operations. + * @Note The initial implementation does actually use standard C++ + * file operations but eventually, there will be another + * layer that caches and manages file meta data too. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code @@ -26,25 +29,21 @@ #include "linden_common.h" -#include "lldiskcache.h" - -#include "llerror.h" -#include "llthread.h" -#include "lltimer.h" +#include "lldir.h" +#include "llfilesystem.h" #include "llfasttimer.h" -#include "llmemory.h" +#include "lldiskcache.h" #include -#include "lldir.h" -const S32 LLDiskCache::READ = 0x00000001; -const S32 LLDiskCache::WRITE = 0x00000002; -const S32 LLDiskCache::READ_WRITE = 0x00000003; // LLDiskCache::READ & LLDiskCache::WRITE -const S32 LLDiskCache::APPEND = 0x00000006; // 0x00000004 & LLDiskCache::WRITE +const S32 LLFileSystem::READ = 0x00000001; +const S32 LLFileSystem::WRITE = 0x00000002; +const S32 LLFileSystem::READ_WRITE = 0x00000003; // LLFileSystem::READ & LLFileSystem::WRITE +const S32 LLFileSystem::APPEND = 0x00000006; // 0x00000004 & LLFileSystem::WRITE static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait"); -LLDiskCache::LLDiskCache(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode) +LLFileSystem::LLFileSystem(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode) { mFileType = file_type; mFileID = file_id; @@ -54,7 +53,7 @@ LLDiskCache::LLDiskCache(const LLUUID &file_id, const LLAssetType::EType file_ty mMode = mode; } -LLDiskCache::~LLDiskCache() +LLFileSystem::~LLFileSystem() { } @@ -124,7 +123,7 @@ const std::string idToFilepath(const std::string id, LLAssetType::EType at) } // static -bool LLDiskCache::getExists(const LLUUID &file_id, const LLAssetType::EType file_type) +bool LLFileSystem::getExists(const LLUUID &file_id, const LLAssetType::EType file_type) { std::string id_str; file_id.toString(id_str); @@ -140,7 +139,7 @@ bool LLDiskCache::getExists(const LLUUID &file_id, const LLAssetType::EType file } // static -bool LLDiskCache::removeFile(const LLUUID &file_id, const LLAssetType::EType file_type) +bool LLFileSystem::removeFile(const LLUUID &file_id, const LLAssetType::EType file_type) { std::string id_str; file_id.toString(id_str); @@ -152,7 +151,7 @@ bool LLDiskCache::removeFile(const LLUUID &file_id, const LLAssetType::EType fil } // static -bool LLDiskCache::renameFile(const LLUUID &old_file_id, const LLAssetType::EType old_file_type, +bool LLFileSystem::renameFile(const LLUUID &old_file_id, const LLAssetType::EType old_file_type, const LLUUID &new_file_id, const LLAssetType::EType new_file_type) { std::string old_id_str; @@ -175,7 +174,7 @@ bool LLDiskCache::renameFile(const LLUUID &old_file_id, const LLAssetType::EType } // static -S32 LLDiskCache::getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type) +S32 LLFileSystem::getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type) { std::string id_str; file_id.toString(id_str); @@ -192,7 +191,7 @@ S32 LLDiskCache::getFileSize(const LLUUID &file_id, const LLAssetType::EType fil return file_size; } -BOOL LLDiskCache::read(U8 *buffer, S32 bytes, BOOL async, F32 priority) +BOOL LLFileSystem::read(U8 *buffer, S32 bytes, BOOL async, F32 priority) { BOOL success = TRUE; @@ -232,7 +231,7 @@ BOOL LLDiskCache::read(U8 *buffer, S32 bytes, BOOL async, F32 priority) return success; } -BOOL LLDiskCache::isReadComplete() +BOOL LLFileSystem::isReadComplete() { if (mReadComplete) { @@ -242,17 +241,17 @@ BOOL LLDiskCache::isReadComplete() return FALSE; } -S32 LLDiskCache::getLastBytesRead() +S32 LLFileSystem::getLastBytesRead() { return mBytesRead; } -BOOL LLDiskCache::eof() +BOOL LLFileSystem::eof() { return mPosition >= getSize(); } -BOOL LLDiskCache::write(const U8 *buffer, S32 bytes) +BOOL LLFileSystem::write(const U8 *buffer, S32 bytes) { std::string id_str; mFileID.toString(id_str); @@ -287,14 +286,14 @@ BOOL LLDiskCache::write(const U8 *buffer, S32 bytes) } //static -BOOL LLDiskCache::writeFile(const U8 *buffer, S32 bytes, const LLUUID &uuid, LLAssetType::EType type) +BOOL LLFileSystem::writeFile(const U8 *buffer, S32 bytes, const LLUUID &uuid, LLAssetType::EType type) { - LLDiskCache file(uuid, type, LLDiskCache::WRITE); + LLFileSystem file(uuid, type, LLFileSystem::WRITE); file.setMaxSize(bytes); return file.write(buffer, bytes); } -BOOL LLDiskCache::seek(S32 offset, S32 origin) +BOOL LLFileSystem::seek(S32 offset, S32 origin) { if (-1 == origin) { @@ -324,32 +323,32 @@ BOOL LLDiskCache::seek(S32 offset, S32 origin) return TRUE; } -S32 LLDiskCache::tell() const +S32 LLFileSystem::tell() const { return mPosition; } -S32 LLDiskCache::getSize() +S32 LLFileSystem::getSize() { - return LLDiskCache::getFileSize(mFileID, mFileType); + return LLFileSystem::getFileSize(mFileID, mFileType); } -S32 LLDiskCache::getMaxSize() +S32 LLFileSystem::getMaxSize() { // offer up a huge size since we don't care what the max is return INT_MAX; } -BOOL LLDiskCache::setMaxSize(S32 size) +BOOL LLFileSystem::setMaxSize(S32 size) { // we don't care what the max size is so we do nothing // and return true to indicate all was okay return TRUE; } -BOOL LLDiskCache::rename(const LLUUID &new_id, const LLAssetType::EType new_type) +BOOL LLFileSystem::rename(const LLUUID &new_id, const LLAssetType::EType new_type) { - LLDiskCache::renameFile(mFileID, mFileType, new_id, new_type); + LLFileSystem::renameFile(mFileID, mFileType, new_id, new_type); mFileID = new_id; mFileType = new_type; @@ -357,31 +356,31 @@ BOOL LLDiskCache::rename(const LLUUID &new_id, const LLAssetType::EType new_type return TRUE; } -BOOL LLDiskCache::remove() +BOOL LLFileSystem::remove() { - LLDiskCache::removeFile(mFileID, mFileType); + LLFileSystem::removeFile(mFileID, mFileType); return TRUE; } // static -void LLDiskCache::initClass() +void LLFileSystem::initClass() { } // static -void LLDiskCache::cleanupClass() +void LLFileSystem::cleanupClass() { } -bool LLDiskCache::isLocked() +bool LLFileSystem::isLocked() { // I don't think we care about this test since there is no locking // TODO: remove this function and calling sites? return FALSE; } -void LLDiskCache::waitForLock() +void LLFileSystem::waitForLock() { // TODO: remove this function and calling sites? } diff --git a/indra/llfilesystem/llfilesystem.h b/indra/llfilesystem/llfilesystem.h index 7ad06a8689..9cddef74a7 100644 --- a/indra/llfilesystem/llfilesystem.h +++ b/indra/llfilesystem/llfilesystem.h @@ -1,6 +1,9 @@ /** - * @file lldiskcacke.h - * @brief Definition of virtual file + * @file filesystem.h + * @brief Simulate local file system operations. + * @Note The initial implementation does actually use standard C++ + * file operations but eventually, there will be another + * layer that caches and manages file meta data too. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,17 +27,17 @@ * $/LicenseInfo$ */ -#ifndef LL_LLDISKCACHE_H -#define LL_LLDISKCACHE_H +#ifndef LL_FILESYSTEM_H +#define LL_FILESYSTEM_H #include "lluuid.h" #include "llassettype.h" -class LLDiskCache +class LLFileSystem { public: - LLDiskCache(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode = LLDiskCache::READ); - ~LLDiskCache(); + LLFileSystem(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode = LLFileSystem::READ); + ~LLFileSystem(); BOOL read(U8 *buffer, S32 bytes, BOOL async = FALSE, F32 priority = 128.f); /* Flawfinder: ignore */ BOOL isReadComplete(); @@ -79,4 +82,4 @@ protected: S32 mBytesRead; }; -#endif // LL_LLDISKCACHE_H +#endif // LL_FILESYSTEM_H diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 31c1edd75e..f38a5e663e 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -42,7 +42,7 @@ // this library includes #include "message.h" #include "llxfermanager.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "lldbstrings.h" #include "lltransfersourceasset.h" @@ -438,7 +438,7 @@ void LLAssetStorage::_cleanupRequests(BOOL all, S32 error) BOOL LLAssetStorage::hasLocalAsset(const LLUUID &uuid, const LLAssetType::EType type) { - return LLDiskCache::getExists(uuid, type); + return LLFileSystem::getExists(uuid, type); } bool LLAssetStorage::findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type, @@ -450,10 +450,10 @@ bool LLAssetStorage::findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetTyp llassert(callback != NULL); } - BOOL exists = LLDiskCache::getExists(uuid, type); + BOOL exists = LLFileSystem::getExists(uuid, type); if (exists) { - LLDiskCache file(uuid, type); + LLFileSystem file(uuid, type); U32 size = file.getSize(); if (size > 0) { @@ -523,8 +523,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, return; } - BOOL exists = LLDiskCache::getExists(uuid, type); - LLDiskCache file(uuid, type); + BOOL exists = LLFileSystem::getExists(uuid, type); + LLFileSystem file(uuid, type); U32 size = exists ? file.getSize() : 0; if (size > 0) @@ -664,7 +664,7 @@ void LLAssetStorage::downloadCompleteCallback( if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file - LLDiskCache vfile(callback_id, callback_type); + LLFileSystem vfile(callback_id, callback_type); if (vfile.getSize() <= 0) { LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset " << callback_id << LL_ENDL; @@ -724,8 +724,8 @@ void LLAssetStorage::getEstateAsset( return; } - BOOL exists = LLDiskCache::getExists(asset_id, atype); - LLDiskCache file(asset_id, atype); + BOOL exists = LLFileSystem::getExists(asset_id, atype); + LLFileSystem file(asset_id, atype); U32 size = exists ? file.getSize() : 0; if (size > 0) @@ -818,7 +818,7 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback( if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file - LLDiskCache vfile(req->getUUID(), req->getAType()); + LLFileSystem vfile(req->getUUID(), req->getAType()); if (vfile.getSize() <= 0) { LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL; @@ -860,8 +860,8 @@ void LLAssetStorage::getInvItemAsset( return; } - exists = LLDiskCache::getExists(asset_id, atype); - LLDiskCache file(asset_id, atype); + exists = LLFileSystem::getExists(asset_id, atype); + LLFileSystem file(asset_id, atype); size = exists ? file.getSize() : 0; if(exists && size < 1) { @@ -961,7 +961,7 @@ void LLAssetStorage::downloadInvItemCompleteCallback( if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file - LLDiskCache vfile(req->getUUID(), req->getType()); + LLFileSystem vfile(req->getUUID(), req->getType()); if (vfile.getSize() <= 0) { LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL; @@ -1396,7 +1396,7 @@ void LLAssetStorage::legacyGetDataCallback(const LLUUID &uuid, if ( !status && !toxic ) { - LLDiskCache file(uuid, type); + LLFileSystem file(uuid, type); std::string uuid_str; diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 376558400c..7031f1aa8c 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -37,7 +37,7 @@ #include "llsdserialize.h" #include "reader.h" // JSON #include "writer.h" // JSON -#include "lldiskcache.h" +#include "llfilesystem.h" #include "message.h" // for getting the port @@ -784,7 +784,7 @@ LLSD HttpCoroutineAdapter::postFileAndSuspend(LLCore::HttpRequest::ptr_t request // scoping for our streams so that they go away when we no longer need them. { LLCore::BufferArrayStream outs(fileData.get()); - LLDiskCache vfile(assetId, assetType, LLDiskCache::READ); + LLFileSystem vfile(assetId, assetType, LLFileSystem::READ); S32 fileSize = vfile.getSize(); U8* fileBuffer; diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp index 7b00a95b00..027283232d 100644 --- a/indra/llmessage/lltransfersourceasset.cpp +++ b/indra/llmessage/lltransfersourceasset.cpp @@ -32,7 +32,7 @@ #include "message.h" #include "lldatapacker.h" #include "lldir.h" -#include "lldiskcache.h" +#include "llfilesystem.h" LLTransferSourceAsset::LLTransferSourceAsset(const LLUUID &request_id, const F32 priority) : LLTransferSource(LLTST_ASSET, request_id, priority), @@ -99,7 +99,7 @@ LLTSCode LLTransferSourceAsset::dataCallback(const S32 packet_id, return LLTS_SKIP; } - LLDiskCache vf(mParams.getAssetID(), mParams.getAssetType(), LLDiskCache::READ); + LLFileSystem vf(mParams.getAssetID(), mParams.getAssetType(), LLFileSystem::READ); if (!vf.getSize()) { @@ -198,7 +198,7 @@ void LLTransferSourceAsset::responderCallback(const LLUUID& uuid, LLAssetType::E if (LL_ERR_NOERR == result) { // Everything's OK. - LLDiskCache vf(uuid, type, LLDiskCache::READ); + LLFileSystem vf(uuid, type, LLFileSystem::READ); tsap->mSize = vf.getSize(); status = LLTS_OK; } diff --git a/indra/llmessage/lltransfersourceasset.h b/indra/llmessage/lltransfersourceasset.h index d9055202ec..585e683cb3 100644 --- a/indra/llmessage/lltransfersourceasset.h +++ b/indra/llmessage/lltransfersourceasset.h @@ -30,7 +30,7 @@ #include "lltransfermanager.h" #include "llassetstorage.h" -class LLDiskCache; +class LLFileSystem; class LLTransferSourceParamsAsset : public LLTransferSourceParams { diff --git a/indra/llmessage/lltransfertargetvfile.cpp b/indra/llmessage/lltransfertargetvfile.cpp index f4a5e71d08..471d687d67 100644 --- a/indra/llmessage/lltransfertargetvfile.cpp +++ b/indra/llmessage/lltransfertargetvfile.cpp @@ -30,7 +30,7 @@ #include "lldatapacker.h" #include "llerror.h" -#include "lldiskcache.h" +#include "llfilesystem.h" //static void LLTransferTargetVFile::updateQueue(bool shutdown) @@ -138,7 +138,7 @@ LLTSCode LLTransferTargetVFile::dataCallback(const S32 packet_id, U8 *in_datap, //LL_INFOS() << "LLTransferTargetFile::dataCallback" << LL_ENDL; //LL_INFOS() << "Packet: " << packet_id << LL_ENDL; - LLDiskCache vf(mTempID, mParams.getAssetType(), LLDiskCache::APPEND); + LLFileSystem vf(mTempID, mParams.getAssetType(), LLFileSystem::APPEND); if (mNeedsCreate) { vf.setMaxSize(mSize); @@ -176,7 +176,7 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status) case LLTS_DONE: if (!mNeedsCreate) { - LLDiskCache file(mTempID, mParams.getAssetType(), LLDiskCache::WRITE); + LLFileSystem file(mTempID, mParams.getAssetType(), LLFileSystem::WRITE); if (!file.rename(mParams.getAssetID(), mParams.getAssetType())) { LL_ERRS() << "LLTransferTargetVFile: rename failed" << LL_ENDL; @@ -195,7 +195,7 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status) { // We're aborting this transfer, we don't want to keep this file. LL_WARNS() << "Aborting vfile transfer for " << mParams.getAssetID() << LL_ENDL; - LLDiskCache vf(mTempID, mParams.getAssetType(), LLDiskCache::APPEND); + LLFileSystem vf(mTempID, mParams.getAssetType(), LLFileSystem::APPEND); vf.remove(); } break; diff --git a/indra/llmessage/lltransfertargetvfile.h b/indra/llmessage/lltransfertargetvfile.h index 4c1bfe22c5..39a9125f1b 100644 --- a/indra/llmessage/lltransfertargetvfile.h +++ b/indra/llmessage/lltransfertargetvfile.h @@ -29,9 +29,9 @@ #include "lltransfermanager.h" #include "llassetstorage.h" -#include "lldiskcache.h" +#include "llfilesystem.h" -class LLDiskCache; +class LLFileSystem; // Lame, an S32 for now until I figure out the deal with how we want to do // error codes. diff --git a/indra/llmessage/llxfer_vfile.cpp b/indra/llmessage/llxfer_vfile.cpp index 95629d5fea..9de9ed379b 100644 --- a/indra/llmessage/llxfer_vfile.cpp +++ b/indra/llmessage/llxfer_vfile.cpp @@ -30,7 +30,7 @@ #include "lluuid.h" #include "llerror.h" #include "llmath.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "lldir.h" // size of chunks read from/written to disk @@ -79,9 +79,9 @@ void LLXfer_VFile::cleanup () if (mTempID.notNull() && mDeleteTempFile) { - if (LLDiskCache::getExists(mTempID, mType)) + if (LLFileSystem::getExists(mTempID, mType)) { - LLDiskCache file(mTempID, mType, LLDiskCache::WRITE); + LLFileSystem file(mTempID, mType, LLFileSystem::WRITE); file.remove(); } else @@ -187,9 +187,9 @@ S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host) delete mVFile; mVFile = NULL; - if(LLDiskCache::getExists(mLocalID, mType)) + if(LLFileSystem::getExists(mLocalID, mType)) { - mVFile = new LLDiskCache(mLocalID, mType, LLDiskCache::READ); + mVFile = new LLFileSystem(mLocalID, mType, LLFileSystem::READ); if (mVFile->getSize() <= 0) { @@ -235,9 +235,9 @@ S32 LLXfer_VFile::reopenFileHandle() if (mVFile == NULL) { - if (LLDiskCache::getExists(mLocalID, mType)) + if (LLFileSystem::getExists(mLocalID, mType)) { - mVFile = new LLDiskCache(mLocalID, mType, LLDiskCache::READ); + mVFile = new LLFileSystem(mLocalID, mType, LLFileSystem::READ); } else { @@ -260,7 +260,7 @@ void LLXfer_VFile::setXferSize (S32 xfer_size) // It would be nice if LLXFers could tell which end of the pipe they were if (! mVFile) { - LLDiskCache file(mTempID, mType, LLDiskCache::APPEND); + LLFileSystem file(mTempID, mType, LLFileSystem::APPEND); file.setMaxSize(xfer_size); } } @@ -315,7 +315,7 @@ S32 LLXfer_VFile::flush() S32 retval = 0; if (mBufferLength) { - LLDiskCache file(mTempID, mType, LLDiskCache::APPEND); + LLFileSystem file(mTempID, mType, LLFileSystem::APPEND); file.write((U8*)mBuffer, mBufferLength); @@ -335,9 +335,9 @@ S32 LLXfer_VFile::processEOF() if (!mCallbackResult) { - if (LLDiskCache::getExists(mTempID, mType)) + if (LLFileSystem::getExists(mTempID, mType)) { - LLDiskCache file(mTempID, mType, LLDiskCache::WRITE); + LLFileSystem file(mTempID, mType, LLFileSystem::WRITE); if (!file.rename(mLocalID, mType)) { LL_WARNS("Xfer") << "Cache rename of temp file failed: unable to rename " << mTempID << " to " << mLocalID << LL_ENDL; diff --git a/indra/llmessage/llxfer_vfile.h b/indra/llmessage/llxfer_vfile.h index d6ac6ff818..d82bab5f6c 100644 --- a/indra/llmessage/llxfer_vfile.h +++ b/indra/llmessage/llxfer_vfile.h @@ -30,7 +30,7 @@ #include "llxfer.h" #include "llassetstorage.h" -class LLDiskCache; +class LLFileSystem; class LLXfer_VFile : public LLXfer { @@ -40,7 +40,7 @@ class LLXfer_VFile : public LLXfer LLUUID mTempID; LLAssetType::EType mType; - LLDiskCache *mVFile; + LLFileSystem *mVFile; std::string mName; diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h index fec0f9784f..94e66f5dc4 100644 --- a/indra/llui/llviewereventrecorder.h +++ b/indra/llui/llviewereventrecorder.h @@ -32,7 +32,6 @@ #include "lldir.h" #include "llsd.h" #include "llfile.h" -#include "lldiskcache.h" #include "lldate.h" #include "llsdserialize.h" #include "llkeyboard.h" diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6181683b9e..12598d028c 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -114,7 +114,7 @@ #include "llprimitive.h" #include "llurlaction.h" #include "llurlentry.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llvolumemgr.h" #include "llxfermanager.h" #include "llphysicsextensions.h" @@ -1876,7 +1876,7 @@ bool LLAppViewer::cleanup() SUBSYSTEM_CLEANUP(LLFolderViewItem); LL_INFOS() << "Cleaning up disk cache" << LL_ENDL; - SUBSYSTEM_CLEANUP(LLDiskCache); + SUBSYSTEM_CLEANUP(LLFileSystem); LL_INFOS() << "Saving Data" << LL_ENDL; @@ -4160,7 +4160,7 @@ bool LLAppViewer::initCache() LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()); - LLDiskCache::initClass(); + LLFileSystem::initClass(); return true; } diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index ad2f3b9f9a..5d010a6f1e 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -52,7 +52,7 @@ #include "lldir.h" #include "llnotificationsutil.h" #include "llviewerstats.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "lluictrlfactory.h" #include "lltrans.h" diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index 42bcb86454..1b9814883e 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -32,7 +32,7 @@ #include "llimagej2c.h" #include "llimagetga.h" #include "llparcel.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llwindow.h" #include "message.h" @@ -201,7 +201,7 @@ void LLFloaterAuction::onClickSnapshot(void* data) LLPointer tga = new LLImageTGA; tga->encode(raw); - LLDiskCache::writeFile(tga->getData(), tga->getDataSize(), self->mImageID, LLAssetType::AT_IMAGE_TGA); + LLFileSystem::writeFile(tga->getData(), tga->getDataSize(), self->mImageID, LLAssetType::AT_IMAGE_TGA); raw->biasedScaleToPowerOfTwo(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT); @@ -209,7 +209,7 @@ void LLFloaterAuction::onClickSnapshot(void* data) LLPointer j2c = new LLImageJ2C; j2c->encode(raw, 0.0f); - LLDiskCache::writeFile(j2c->getData(), j2c->getDataSize(), self->mImageID, LLAssetType::AT_TEXTURE); + LLFileSystem::writeFile(j2c->getData(), j2c->getDataSize(), self->mImageID, LLAssetType::AT_TEXTURE); self->mImage = LLViewerTextureManager::getLocalTexture((LLImageRaw*)raw, FALSE); gGL.getTexUnit(0)->bind(self->mImage); diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index 303b4836e4..08f3b577b4 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -32,7 +32,7 @@ #include "lldatapacker.h" #include "lldir.h" #include "llnotificationsutil.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llapr.h" #include "llstring.h" @@ -997,7 +997,7 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata) LLDataPackerBinaryBuffer dp(buffer, file_size); if (motionp->serialize(dp)) { - LLDiskCache file(motionp->getID(), LLAssetType::AT_ANIMATION, LLDiskCache::APPEND); + LLFileSystem file(motionp->getID(), LLAssetType::AT_ANIMATION, LLFileSystem::APPEND); S32 size = dp.getCurrentSize(); file.setMaxSize(size); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 057c4d0d5c..0fa5f8e4df 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -77,7 +77,7 @@ #include "llspinctrl.h" #include "lltoggleablemenu.h" #include "lltrans.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llcallbacklist.h" #include "llviewerobjectlist.h" #include "llanimationstates.h" diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index d2ab15a9b4..0375c15467 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -36,7 +36,7 @@ #include "llglheaders.h" #include "llregionflags.h" #include "llstl.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llxfermanager.h" #include "indra_constants.h" #include "message.h" @@ -2239,7 +2239,7 @@ void LLPanelEstateCovenant::onLoadComplete(const LLUUID& asset_uuid, { if(0 == status) { - LLDiskCache file(asset_uuid, type, LLDiskCache::READ); + LLFileSystem file(asset_uuid, type, LLFileSystem::READ); S32 file_length = file.getSize(); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 97db905467..3ef80300ef 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -44,7 +44,7 @@ #include "llnotificationsutil.h" #include "llstring.h" #include "llsys.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "mean_collision_data.h" #include "message.h" #include "v3math.h" @@ -899,7 +899,7 @@ void LLFloaterReporter::takeScreenshot(bool use_prev_screenshot) mResourceDatap->mAssetInfo.setDescription("screenshot_descr"); // store in cache - LLDiskCache::writeFile(upload_data->getData(), + LLFileSystem::writeFile(upload_data->getData(), upload_data->getDataSize(), mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType); diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 96da13915c..1aeb727172 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -40,7 +40,7 @@ #include "lltextbox.h" #include "llui.h" #include "lluictrlfactory.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "message.h" #include "llstartup.h" // login_alert_done #include "llcorehttputil.h" diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 82feb891bc..9f2119281d 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -42,7 +42,7 @@ #include "llnotificationsutil.h" #include "llstl.h" #include "llstring.h" // todo: remove -#include "lldiskcache.h" +#include "llfilesystem.h" #include "message.h" // newview @@ -1055,7 +1055,7 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid, if (0 == status) { - LLDiskCache file(asset_uuid, type, LLDiskCache::READ); + LLFileSystem file(asset_uuid, type, LLFileSystem::READ); S32 size = file.getSize(); std::vector buffer(size+1); diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index 5661b2525b..747212ba55 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -33,7 +33,7 @@ #include "llappviewer.h" #include "llagent.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llviewerstats.h" // Globals @@ -122,7 +122,7 @@ void LLLandmarkList::processGetAssetReply( { if( status == 0 ) { - LLDiskCache file(uuid, type); + LLFileSystem file(uuid, type); S32 file_length = file.getSize(); std::vector buffer(file_length + 1); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 011b187b58..a0d591dc47 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -49,7 +49,7 @@ #include "llsdutil_math.h" #include "llsdserialize.h" #include "llthread.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llviewercontrol.h" #include "llviewerinventory.h" #include "llviewermenufile.h" @@ -1335,7 +1335,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) { //check cache for mesh skin info - LLDiskCache file(mesh_id, LLAssetType::AT_MESH); + LLFileSystem file(mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) { U8* buffer = new(std::nothrow) U8[size]; @@ -1431,7 +1431,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) { //check cache for mesh skin info - LLDiskCache file(mesh_id, LLAssetType::AT_MESH); + LLFileSystem file(mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) { U8* buffer = new(std::nothrow) U8[size]; @@ -1528,7 +1528,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) { //check cache for mesh physics shape info - LLDiskCache file(mesh_id, LLAssetType::AT_MESH); + LLFileSystem file(mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) { LLMeshRepository::sCacheBytesRead += size; @@ -1633,7 +1633,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, bool c { //look for mesh in asset in cache - LLDiskCache file(mesh_params.getSculptID(), LLAssetType::AT_MESH); + LLFileSystem file(mesh_params.getSculptID(), LLAssetType::AT_MESH); S32 size = file.getSize(); @@ -1712,7 +1712,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, { //check cache for mesh asset - LLDiskCache file(mesh_id, LLAssetType::AT_MESH); + LLFileSystem file(mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) { U8* buffer = new(std::nothrow) U8[size]; @@ -3240,7 +3240,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b // only allocate as much space in the cache as is needed for the local cache data_size = llmin(data_size, bytes); - LLDiskCache file(mesh_id, LLAssetType::AT_MESH, LLDiskCache::WRITE); + LLFileSystem file(mesh_id, LLAssetType::AT_MESH, LLFileSystem::WRITE); if (file.getMaxSize() >= bytes || file.setMaxSize(bytes)) { LLMeshRepository::sCacheBytesWritten += data_size; @@ -3312,7 +3312,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body if (result == MESH_OK) { // good fetch from sim, write to cache - LLDiskCache file(mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLDiskCache::WRITE); + LLFileSystem file(mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLFileSystem::WRITE); S32 offset = mOffset; S32 size = mRequestedBytes; @@ -3376,7 +3376,7 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* && gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size)) { // good fetch from sim, write to cache - LLDiskCache file(mMeshID, LLAssetType::AT_MESH, LLDiskCache::WRITE); + LLFileSystem file(mMeshID, LLAssetType::AT_MESH, LLFileSystem::WRITE); S32 offset = mOffset; S32 size = mRequestedBytes; @@ -3424,7 +3424,7 @@ void LLMeshDecompositionHandler::processData(LLCore::BufferArray * /* body */, S && gMeshRepo.mThread->decompositionReceived(mMeshID, data, data_size)) { // good fetch from sim, write to cache - LLDiskCache file(mMeshID, LLAssetType::AT_MESH, LLDiskCache::WRITE); + LLFileSystem file(mMeshID, LLAssetType::AT_MESH, LLFileSystem::WRITE); S32 offset = mOffset; S32 size = mRequestedBytes; @@ -3471,7 +3471,7 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * /* body */, S3 && gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size) == MESH_OK) { // good fetch from sim, write to cache for caching - LLDiskCache file(mMeshID, LLAssetType::AT_MESH, LLDiskCache::WRITE); + LLFileSystem file(mMeshID, LLAssetType::AT_MESH, LLFileSystem::WRITE); S32 offset = mOffset; S32 size = mRequestedBytes; diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index ac2d449621..90f6d23a61 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -32,7 +32,7 @@ // llcommon #include "llcommonutils.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llaccordionctrltab.h" #include "llappearancemgr.h" diff --git a/indra/newview/llpostcard.cpp b/indra/newview/llpostcard.cpp index 1fd57ef555..071fc31d27 100644 --- a/indra/newview/llpostcard.cpp +++ b/indra/newview/llpostcard.cpp @@ -28,7 +28,7 @@ #include "llpostcard.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llviewerregion.h" #include "message.h" diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index c7f8f790f4..371153aac3 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -47,7 +47,7 @@ #include "llradiogroup.h" #include "llresmgr.h" #include "lltrans.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llviewerstats.h" @@ -852,7 +852,7 @@ void LLPreviewGesture::onLoadComplete(const LLUUID& asset_uuid, { if (0 == status) { - LLDiskCache file(asset_uuid, type, LLDiskCache::READ); + LLFileSystem file(asset_uuid, type, LLFileSystem::READ); S32 size = file.getSize(); std::vector buffer(size+1); @@ -1137,7 +1137,7 @@ void LLPreviewGesture::saveIfNeeded() tid.generate(); assetId = tid.makeAssetID(gAgent.getSecureSessionID()); - LLDiskCache file(assetId, LLAssetType::AT_GESTURE, LLDiskCache::APPEND); + LLFileSystem file(assetId, LLAssetType::AT_GESTURE, LLFileSystem::APPEND); S32 size = dp.getCurrentSize(); file.setMaxSize(size); diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 0b21ff5047..0bccf1d06f 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -46,7 +46,7 @@ #include "llselectmgr.h" #include "lltrans.h" #include "llviewertexteditor.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llviewerinventory.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" @@ -337,7 +337,7 @@ void LLPreviewNotecard::onLoadComplete(const LLUUID& asset_uuid, { if(0 == status) { - LLDiskCache file(asset_uuid, type, LLDiskCache::READ); + LLFileSystem file(asset_uuid, type, LLFileSystem::READ); S32 file_length = file.getSize(); @@ -452,7 +452,7 @@ void LLPreviewNotecard::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, // script actually changed the asset. if (nc->hasEmbeddedInventory()) { - LLDiskCache::removeFile(newAssetId, LLAssetType::AT_NOTECARD); + LLFileSystem::removeFile(newAssetId, LLAssetType::AT_NOTECARD); } if (newItemId.isNull()) { @@ -477,7 +477,7 @@ void LLPreviewNotecard::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUI { if (nc->hasEmbeddedInventory()) { - LLDiskCache::removeFile(newAssetId, LLAssetType::AT_NOTECARD); + LLFileSystem::removeFile(newAssetId, LLAssetType::AT_NOTECARD); } nc->setAssetId(newAssetId); nc->refreshFromInventory(); @@ -556,7 +556,7 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem, bool sync) tid.generate(); asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - LLDiskCache file(asset_id, LLAssetType::AT_NOTECARD, LLDiskCache::APPEND); + LLFileSystem file(asset_id, LLAssetType::AT_NOTECARD, LLFileSystem::APPEND); LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID, diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index c2b687cf3b..eae6c28e35 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -51,7 +51,7 @@ #include "llsdserialize.h" #include "llslider.h" #include "lltooldraganddrop.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llagent.h" #include "llmenugl.h" @@ -1715,7 +1715,7 @@ void LLPreviewLSL::onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType t { if(0 == status) { - LLDiskCache file(asset_uuid, type); + LLFileSystem file(asset_uuid, type); S32 file_length = file.getSize(); std::vector buffer(file_length+1); @@ -2020,7 +2020,7 @@ void LLLiveLSLEditor::onLoadComplete(const LLUUID& asset_id, void LLLiveLSLEditor::loadScriptText(const LLUUID &uuid, LLAssetType::EType type) { - LLDiskCache file(uuid, type); + LLFileSystem file(uuid, type); S32 file_length = file.getSize(); std::vector buffer(file_length + 1); file.read((U8*)&buffer[0], file_length); diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 62dc9f24bd..2db0fe6fa4 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -57,7 +57,7 @@ #include "llinventorymodel.h" #include "llassetstorage.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "lldrawpoolwater.h" #include @@ -303,7 +303,7 @@ void LLSettingsVOBase::onAssetDownloadComplete(const LLUUID &asset_id, S32 statu LLSettingsBase::ptr_t settings; if (!status) { - LLDiskCache file(asset_id, LLAssetType::AT_SETTINGS, LLDiskCache::READ); + LLFileSystem file(asset_id, LLAssetType::AT_SETTINGS, LLFileSystem::READ); S32 size = file.getSize(); std::string buffer(size + 1, '\0'); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 50523e981a..795563e295 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -31,6 +31,7 @@ #include "llagentbenefits.h" #include "llagentcamera.h" #include "llagentui.h" +#include "llfilesystem.h" #include "llcombobox.h" #include "llfloaterperms.h" #include "llfloaterreg.h" @@ -50,7 +51,6 @@ #include "llviewercontrol.h" #include "llviewermenufile.h" // upload_new_resource() #include "llviewerstats.h" -#include "lldiskcache.h" #include "llwindow.h" #include "llworld.h" #include @@ -1005,7 +1005,7 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) if (formatted->encode(scaled, 0.0f)) { - LLDiskCache::writeFile(formatted->getData(), formatted->getDataSize(), new_asset_id, LLAssetType::AT_TEXTURE); + LLFileSystem::writeFile(formatted->getData(), formatted->getDataSize(), new_asset_id, LLAssetType::AT_TEXTURE); std::string pos_string; LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL); std::string who_took_it; diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 3b86f3910d..df3ff1a3c7 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -28,7 +28,7 @@ #include "llviewerassetstorage.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "message.h" #include "llagent.h" @@ -152,13 +152,13 @@ void LLViewerAssetStorage::storeAssetData( if (mUpstreamHost.isOk()) { - if (LLDiskCache::getExists(asset_id, asset_type)) + if (LLFileSystem::getExists(asset_id, asset_type)) { // Pack data into this packet if we can fit it. U8 buffer[MTUBYTES]; buffer[0] = 0; - LLDiskCache vfile(asset_id, asset_type, LLDiskCache::READ); + LLFileSystem vfile(asset_id, asset_type, LLFileSystem::READ); S32 asset_size = vfile.getSize(); LLAssetRequest *req = new LLAssetRequest(asset_id, asset_type); @@ -180,7 +180,7 @@ void LLViewerAssetStorage::storeAssetData( else { // LLAssetStorage metric: Successful Request - S32 size = LLDiskCache::getFileSize(asset_id, asset_type); + S32 size = LLFileSystem::getFileSize(asset_id, asset_type); const char *message = "Added to upload queue"; reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, size, MR_OKAY, __FILE__, __LINE__, message ); @@ -291,7 +291,7 @@ void LLViewerAssetStorage::storeAssetData( legacy->mUpCallback = callback; legacy->mUserData = user_data; - LLDiskCache file(asset_id, asset_type, LLDiskCache::WRITE); + LLFileSystem file(asset_id, asset_type, LLFileSystem::WRITE); file.setMaxSize(size); @@ -527,7 +527,7 @@ void LLViewerAssetStorage::assetRequestCoro( // case. LLUUID temp_id; temp_id.generate(); - LLDiskCache vf(temp_id, atype, LLDiskCache::WRITE); + LLFileSystem vf(temp_id, atype, LLFileSystem::WRITE); vf.setMaxSize(size); req->mBytesFetched = size; if (!vf.write(raw.data(),size)) diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index e65bdc1aea..972c89de34 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -30,7 +30,7 @@ #include "llassetstorage.h" #include "llcorehttputil.h" -class LLDiskCache; +class LLFileSystem; class LLViewerAssetRequest; diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index d62962514c..fb3ca69d5d 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -45,7 +45,7 @@ #include "llviewerassetupload.h" #include "llappviewer.h" #include "llviewerstats.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llgesturemgr.h" #include "llpreviewnotecard.h" #include "llpreviewgesture.h" @@ -472,7 +472,7 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile() infile.open(filename, LL_APR_RB, NULL, &file_size); if (infile.getFileHandle()) { - LLDiskCache file(getAssetId(), assetType, LLDiskCache::WRITE); + LLFileSystem file(getAssetId(), assetType, LLFileSystem::WRITE); file.setMaxSize(file_size); @@ -565,7 +565,7 @@ LLSD LLBufferedAssetUploadInfo::prepareUpload() if (getAssetId().isNull()) generateNewAssetId(); - LLDiskCache file(getAssetId(), getAssetType(), LLDiskCache::APPEND); + LLFileSystem file(getAssetId(), getAssetType(), LLFileSystem::APPEND); S32 size = mContents.length() + 1; file.setMaxSize(size); @@ -597,7 +597,7 @@ LLUUID LLBufferedAssetUploadInfo::finishUpload(LLSD &result) if (mStoredToCache) { LLAssetType::EType assetType(getAssetType()); - LLDiskCache::renameFile(getAssetId(), assetType, newAssetId, assetType); + LLFileSystem::renameFile(getAssetId(), assetType, newAssetId, assetType); } if (mTaskUpload) diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 6d4e12528d..b34f4b5016 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -53,7 +53,6 @@ #include "llviewercontrol.h" // gSavedSettings #include "llviewertexturelist.h" #include "lluictrlfactory.h" -#include "lldiskcache.h" #include "llviewerinventory.h" #include "llviewermenu.h" // gMenuHolder #include "llviewerparcelmgr.h" diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 10ee92c130..4ab6fcc580 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -44,7 +44,7 @@ #include "llteleportflags.h" #include "lltoastnotifypanel.h" #include "lltransactionflags.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llxfermanager.h" #include "mean_collision_data.h" @@ -6816,7 +6816,7 @@ void onCovenantLoadComplete(const LLUUID& asset_uuid, std::string covenant_text; if(0 == status) { - LLDiskCache file(asset_uuid, type, LLDiskCache::READ); + LLFileSystem file(asset_uuid, type, LLFileSystem::READ); S32 file_length = file.getSize(); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 874982ed60..7ea702b0c9 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -33,7 +33,6 @@ #include "llfloaterreg.h" #include "llmemory.h" #include "lltimer.h" -#include "lldiskcache.h" #include "llappviewer.h" diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp index 199f7f710a..4c2fbcf837 100644 --- a/indra/newview/llviewertexlayer.cpp +++ b/indra/newview/llviewertexlayer.cpp @@ -31,7 +31,6 @@ #include "llagent.h" #include "llimagej2c.h" #include "llnotificationsutil.h" -#include "lldiskcache.h" #include "llviewerregion.h" #include "llglslshader.h" #include "llvoavatarself.h" diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index f12ab59e2b..d7377a2983 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -39,7 +39,6 @@ #include "llimagej2c.h" #include "llimagetga.h" #include "llstl.h" -#include "lldiskcache.h" #include "message.h" #include "lltimer.h" diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 57a2421065..07997e02a5 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -54,7 +54,7 @@ class LLTexturePipelineTester ; typedef void (*loaded_callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); -class LLDiskCache; +class LLFileSystem; class LLMessageSystem; class LLViewerMediaImpl ; class LLVOVolume ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index e0727d51ba..38fccba169 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -41,7 +41,7 @@ #include "llsdserialize.h" #include "llsys.h" -#include "lldiskcache.h" +#include "llfilesystem.h" #include "llxmltree.h" #include "message.h" -- cgit v1.3