From 5536f7b7ecd4e6a435ffb2daae5a1a01f20e54f8 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Mon, 8 Mar 2021 05:35:40 -0500
Subject: [PATCH] Large rewrite of cache for more efficient file io and safety
 with more extensive error handling

---
 indra/llaudio/llaudiodecodemgr.cpp        |   2 +-
 indra/llcharacter/llkeyframemotion.cpp    |  25 ++-
 indra/llfilesystem/llfilesystem.cpp       | 216 ++++++++++++----------
 indra/llfilesystem/llfilesystem.h         |  86 +++++----
 indra/llmessage/llassetstorage.cpp        |  55 +++---
 indra/llmessage/llcorehttputil.cpp        |  18 +-
 indra/llmessage/lltransfersourceasset.cpp |   2 +-
 indra/llmessage/lltransfertargetvfile.cpp |   8 +-
 indra/llmessage/llxfer_vfile.cpp          |  49 +++--
 indra/llmessage/llxfer_vfile.h            |   4 +-
 indra/newview/alaoengine.cpp              |  25 +--
 indra/newview/llfloaterauction.cpp        |  12 +-
 indra/newview/llfloaterbvhpreview.cpp     |   4 +-
 indra/newview/llfloaterregioninfo.cpp     |  47 ++---
 indra/newview/llfloaterreporter.cpp       |   6 +-
 indra/newview/llgesturemgr.cpp            | 143 +++++++-------
 indra/newview/lllandmarklist.cpp          |  60 +++---
 indra/newview/llmeshrepository.cpp        |  32 ++--
 indra/newview/llpreviewgesture.cpp        |  81 +++++---
 indra/newview/llpreviewnotecard.cpp       |  92 +++++----
 indra/newview/llpreviewscript.cpp         |  89 +++++----
 indra/newview/llsettingsvo.cpp            |  44 +++--
 indra/newview/llsnapshotlivepreview.cpp   |  57 ++++--
 indra/newview/llviewerassetstorage.cpp    |  35 +++-
 indra/newview/llviewerassetupload.cpp     |  21 ++-
 indra/newview/llviewermessage.cpp         |  58 +++---
 26 files changed, 758 insertions(+), 513 deletions(-)

diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index af8a0a88f04..1e805cb9901 100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -207,7 +207,7 @@ BOOL LLVorbisDecodeState::initDecode()
 	LL_DEBUGS("AudioEngine") << "Initing decode from vfile: " << mUUID << LL_ENDL;
 
 	mInFilep = new LLFileSystem(mUUID, LLAssetType::AT_SOUND);
-	if (!mInFilep || !mInFilep->getSize())
+	if (!mInFilep || !mInFilep->open() || !mInFilep->getSize())
 	{
 		LL_WARNS("AudioEngine") << "unable to open vorbis source vfile for reading" << LL_ENDL;
 		delete mInFilep;
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index 15ffe1c5d2f..ab3959e7a13 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -341,12 +341,11 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
 		// Load named file by concatenating the character prefix with the motion name.
 		// Load data into a buffer to be parsed.
 		//-------------------------------------------------------------------------
-		LLFileSystem* anim_file = new LLFileSystem(mID, LLAssetType::AT_ANIMATION);
-		if (!anim_file || !anim_file->getSize())
-		{
-			delete anim_file;
-			anim_file = NULL;
 
+
+		LLFileSystem anim_file(mID, LLAssetType::AT_ANIMATION);
+		if (!anim_file.open() || !anim_file.getSize())
+		{
 			// request asset over network on next call to load
 			mAssetStatus = ASSET_NEEDS_FETCH;
 
@@ -354,11 +353,11 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
 		}
 		else
 		{
-			anim_file_size = anim_file->getSize();
+			anim_file_size = anim_file.getSize();
 			anim_data = new(std::nothrow) U8[anim_file_size];
 			if (anim_data)
 			{
-				success = anim_file->read(anim_data, anim_file_size);	/*Flawfinder: ignore*/
+				success = anim_file.read(anim_data, anim_file_size);	/*Flawfinder: ignore*/
 				if (!success)
 				{
 					delete[] anim_data;
@@ -369,8 +368,6 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
 			{
 				LL_WARNS() << "Failed to allocate buffer: " << anim_file_size << mID << LL_ENDL;
 			}
-			delete anim_file;
-			anim_file = NULL;
 		}
 	}
 	else
@@ -2129,10 +2126,18 @@ void LLKeyframeMotion::onLoadComplete(const LLUUID& asset_uuid,
 				return;
 			}
 			LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
+			if (!file.open())
+			{
+				return;
+			}
 			S32 size = file.getSize();
 			
 			U8* buffer = new U8[size];
-			file.read((U8*)buffer, size);	/*Flawfinder: ignore*/
+			if (!file.read((U8*)buffer, size))	/*Flawfinder: ignore*/
+			{
+				delete[] buffer;
+				return;
+			}
 
 			LL_DEBUGS("Animation") << "Loading keyframe data for: " << motionp->getName() << ":" << motionp->getID() << " (" << size << " bytes)" << LL_ENDL;
 			
diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp
index 20c4d6a0da6..80f18f55b0f 100644
--- a/indra/llfilesystem/llfilesystem.cpp
+++ b/indra/llfilesystem/llfilesystem.cpp
@@ -37,10 +37,10 @@
 #include <boost/filesystem.hpp>
 
 LLFileSystem::LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_type, S32 mode)
-	: mFileID(file_id), 
+    : mFileID(file_id),
     mFileType(file_type),
-	mPosition(0),
-	mMode(mode),
+    mPosition(0),
+    mMode(mode),
     mBytesRead(0)
 {
     const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type);
@@ -51,75 +51,79 @@ LLFileSystem::LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_
 #endif
 }
 
-// static
-bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType file_type)
+bool LLFileSystem::open()
 {
-    LLFileSystem file(file_id, file_type, READ);
-    return file.exists();
-}
+    switch (mMode)
+    {
+    case READ: mFile = LLFile::fopen(mFilePath, TEXT("rb")); break;
+    case WRITE: mFile = LLFile::fopen(mFilePath, TEXT("wb")); break;
+    case READ_WRITE: mFile = LLFile::fopen(mFilePath, TEXT("rb+")); break;
+    case APPEND: mFile = LLFile::fopen(mFilePath, TEXT("ab")); break;
+    }
+    if (mMode == READ_WRITE && !mFile)
+        mFile = LLFile::fopen(mFilePath, TEXT("wb+"));
 
-// static
-bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType file_type)
-{
-    LLFileSystem file(file_id, file_type, READ_WRITE);
-    return file.remove();
+    return mFile;
 }
 
-// static
-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)
+void LLFileSystem::close()
 {
-    LLFileSystem file(old_file_id, old_file_type, READ_WRITE);
-    return file.rename(new_file_id, new_file_type);
+    mFile.close();
 }
 
 BOOL LLFileSystem::read(U8* buffer, S32 bytes)
 {
+    if (!mFile)
+    {
+        LL_WARNS() << "Attempt to write to file " << mFileID << " that is not open" << LL_ENDL;
+        return FALSE;
+    }
+
+    if (!(mMode & READ))
+    {
+        LL_WARNS() << "Attempt to read from file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL;
+        return FALSE;
+    }
+
     BOOL success = TRUE;
 
-    LLUniqueFile filep = LLFile::fopen(mFilePath, TEXT("rb"));
-    if (filep)
+    fseek(mFile, mPosition, SEEK_SET);
+    size_t bytes_read = fread((void*)buffer, 1, bytes, mFile);
+    if (bytes_read == bytes)
     {
-        fseek(filep, mPosition, SEEK_SET);
-        size_t bytes_read = fread((void*)buffer, 1, bytes, filep);
-        if (bytes_read == bytes)
-        {
-            mBytesRead = bytes;
-        }
-        else
+        mBytesRead = bytes_read;
+    }
+    else
+    {
+        fseek(mFile, 0L, SEEK_END);
+        long fsize = ftell(mFile);
+        if (mPosition < fsize)
         {
-            fseek(filep, 0L, SEEK_END);
-            long fsize = ftell(filep);
-            fseek(filep, mPosition, SEEK_SET);
-            if (mPosition < fsize)
+            fseek(mFile, mPosition, SEEK_SET);
+            long rsize = fsize - mPosition;
+            size_t bytes_read = fread((void*)buffer, 1, rsize, mFile);
+            if (bytes_read == rsize)
             {
-                long rsize = fsize - mPosition;
-                size_t bytes_read = fread((void*)buffer, 1, rsize, filep);
-                if (bytes_read == rsize)
-                {
-                    mBytesRead = rsize;
-                }
-                else
-                {
-                    success = FALSE;
-                }
+                mBytesRead = bytes_read;
             }
             else
             {
                 success = FALSE;
             }
         }
-
-        if (!success)
+        else
         {
-            mBytesRead = 0;
+            success = FALSE;
         }
+    }
 
-        filep.close();
-
-        mPosition += mBytesRead;
+    if (success == FALSE)
+    {
+        mBytesRead = 0;
     }
 
+    mPosition += mBytesRead;
+
     // update the last access time for the file - this is required
     // even though we are reading and not writing because this is the
     // way the cache works - it relies on a valid "last accessed time" for
@@ -141,71 +145,53 @@ BOOL LLFileSystem::eof()
 
 BOOL LLFileSystem::write(const U8* buffer, S32 bytes)
 {
-    BOOL success = FALSE;
+    if (!mFile)
+    {
+        LL_WARNS() << "Attempt to write to file " << mFileID << " that is not open" << LL_ENDL;
+        return FALSE;
+    }
 
-    LLUniqueFile filep;
-    if (mMode == READ_WRITE)
+    if (!(mMode & WRITE) || !(mMode & APPEND))
     {
-        filep = LLFile::fopen(mFilePath, TEXT("rb+"));
-        if (filep)
-        {
-            fseek(filep, mPosition, SEEK_SET);
+        LL_WARNS() << "Attempt to write to file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL;
+        return FALSE;
+    }
 
-            size_t bytes_written = fwrite((const void*)buffer, 1, bytes, filep);
-            if (bytes_written == bytes)
-            {
-                mPosition += bytes_written;
+    BOOL success = FALSE;
+    if (mMode == READ_WRITE)
+    {
+        fseek(mFile, mPosition, SEEK_SET);
 
-                success = TRUE;
-            }
-        }
-        else
+        size_t bytes_written = fwrite((const void*)buffer, 1, bytes, mFile);
+        if (bytes_written == bytes)
         {
-            filep = LLFile::fopen(mFilePath, TEXT("wb"));
-            if (filep)
-            {
-                size_t bytes_written = fwrite((const void*)buffer, 1, bytes, filep);
-
-                if (bytes_written == bytes)
-                {
-                    mPosition = bytes_written;
+            mPosition += bytes_written;
 
-                    success = TRUE;
-                }
-            }
+            success = TRUE;
         }
     }
     else if (mMode == APPEND)
     {
-        filep = LLFile::fopen(mFilePath, TEXT("ab"));
-        if (filep)
-        {
-            fseek(filep, 0L, SEEK_END);
-            long fsize = ftell(filep);
-
-            size_t bytes_written = fwrite((const void*)buffer, 1, bytes, filep);
+        fseek(mFile, 0L, SEEK_END);
+        long fsize = ftell(mFile);
 
-            if (bytes_written == bytes)
-            {
-                mPosition = fsize + bytes_written;
+        size_t bytes_written = fwrite((const void*)buffer, 1, bytes, mFile);
+        if (bytes_written == bytes)
+        {
+            mPosition = fsize + bytes_written;
 
-                success = TRUE;
-            }
+            success = TRUE;
         }
     }
     else
     {
-        filep = LLFile::fopen(mFilePath, TEXT("wb"));
-        if (filep)
-        {
-            size_t bytes_written = fwrite((const void*)buffer, 1, bytes, filep);
+        size_t bytes_written = fwrite((const void*)buffer, 1, bytes, mFile);
 
-            if (bytes_written == bytes)
-            {
-                mPosition = bytes_written;
+        if (bytes_written == bytes)
+        {
+            mPosition = bytes_written;
 
-                success = TRUE;
-            }
+            success = TRUE;
         }
     }
 
@@ -250,11 +236,19 @@ S32 LLFileSystem::tell() const
 S32 LLFileSystem::getSize()
 {
     S32 file_size = 0;
-    LLUniqueFile filep = LLFile::fopen(mFilePath, TEXT("rb"));
-    if (filep)
+    if (mFile)
     {
-        fseek(filep, 0L, SEEK_END);
-        file_size = ftell(filep);
+        fseek(mFile, 0L, SEEK_END);
+        file_size = ftell(mFile);
+        fseek(mFile, mPosition, SEEK_SET);
+    }
+    else
+    {
+        llstat stat;
+        if (LLFile::stat(mFilePath, &stat) == 0)
+        {
+            file_size = stat.st_size;
+        }
     }
 
     return file_size;
@@ -268,6 +262,8 @@ S32 LLFileSystem::getMaxSize()
 
 BOOL LLFileSystem::rename(const LLUUID& new_id, const LLAssetType::EType new_type)
 {
+    close();
+
 #if LL_WINDOWS
     boost::filesystem::path new_filename = ll_convert_string_to_wide(LLDiskCache::metaDataToFilepath(new_id, new_type));
 #else
@@ -296,6 +292,8 @@ BOOL LLFileSystem::rename(const LLUUID& new_id, const LLAssetType::EType new_typ
 
 BOOL LLFileSystem::remove()
 {
+    close();
+
     LLFile::remove(mFilePath, ENOENT);
 
     return TRUE;
@@ -340,3 +338,25 @@ void LLFileSystem::updateFileAccessTime()
         boost::filesystem::last_write_time(mFilePath, cur_time);
     }
 }
+
+// static
+bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType file_type)
+{
+    LLFileSystem file(file_id, file_type, READ);
+    return file.exists();
+}
+
+// static
+bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType file_type)
+{
+    LLFileSystem file(file_id, file_type, READ_WRITE);
+    return file.remove();
+}
+
+// static
+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)
+{
+    LLFileSystem file(old_file_id, old_file_type, READ_WRITE);
+    return file.rename(new_file_id, new_file_type);
+}
\ No newline at end of file
diff --git a/indra/llfilesystem/llfilesystem.h b/indra/llfilesystem/llfilesystem.h
index 63b46e8e759..f19f3c56811 100644
--- a/indra/llfilesystem/llfilesystem.h
+++ b/indra/llfilesystem/llfilesystem.h
@@ -38,54 +38,58 @@
 
 class LLFileSystem
 {
-    public:
-        LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_type, S32 mode = LLFileSystem::READ);
-        ~LLFileSystem() = default;
+public:
+    LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_type, S32 mode = LLFileSystem::READ);
+    ~LLFileSystem() = default;
 
-        BOOL read(U8* buffer, S32 bytes);
-        S32  getLastBytesRead();
-        BOOL eof();
+    bool open();
+    void close();
 
-        BOOL write(const U8* buffer, S32 bytes);
-        BOOL seek(S32 offset, S32 origin = -1);
-        S32  tell() const;
+    bool is_open() { return mFile; }
 
-        S32 getSize();
-        S32 getMaxSize();
-        BOOL rename(const LLUUID& new_id, const LLAssetType::EType new_type);
-        BOOL remove();
-        BOOL exists();
+    BOOL read(U8* buffer, S32 bytes);
+    S32  getLastBytesRead();
+    BOOL eof();
 
-        /**
-         * Update the "last write time" of a file to "now". This must be called whenever a
-         * file in the cache is read (not written) so that the last time the file was
-         * accessed is up to date (This is used in the mechanism for purging the cache)
-         */
-        void updateFileAccessTime();
+    BOOL write(const U8* buffer, S32 bytes);
+    BOOL seek(S32 offset, S32 origin = -1);
+    S32  tell() const;
 
-        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);
+    S32 getSize();
+    S32 getMaxSize();
+    BOOL rename(const LLUUID& new_id, const LLAssetType::EType new_type);
+    BOOL remove();
+    BOOL exists();
 
-    public:
-		enum
-		{
-			READ = 0x00000001,
-			WRITE = 0x00000002,
-			READ_WRITE = 0x00000003,  // LLFileSystem::READ & LLFileSystem::WRITE
-			APPEND = 0x00000006,  // 0x00000004 & LLFileSystem::WRITE
-		};
+    /**
+     * Update the "last write time" of a file to "now". This must be called whenever a
+     * file in the cache is read (not written) so that the last time the file was
+     * accessed is up to date (This is used in the mechanism for purging the cache)
+     */
+    void updateFileAccessTime();
 
-    protected:
-        boost::filesystem::path mFilePath;
-        LLUUID  mFileID;
-        LLAssetType::EType mFileType;
-        S32     mPosition;
-        S32     mMode;
-        S32     mBytesRead;
-//private:
-//    static const std::string idToFilepath(const std::string id, LLAssetType::EType at);
+    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);
+
+public:
+    enum
+    {
+        READ = 0x00000001,
+        WRITE = 0x00000002,
+        READ_WRITE = 0x00000003,  // LLFileSystem::READ & LLFileSystem::WRITE
+        APPEND = 0x00000006,  // 0x00000004 & LLFileSystem::WRITE
+    };
+
+protected:
+    boost::filesystem::path mFilePath;
+    LLUniqueFile mFile;
+    LLUUID  mFileID;
+    LLAssetType::EType mFileType;
+    S32     mPosition;
+    S32     mMode;
+    S32     mBytesRead;
 };
 
 #endif  // LL_FILESYSTEM_H
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index 318c554e753..05933e24409 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -430,12 +430,11 @@ bool LLAssetStorage::findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetTyp
         llassert(callback != NULL);
     }
 
-    BOOL exists = LLFileSystem::getExists(uuid, type);
-    if (exists)
+    LLFileSystem file(uuid, type);
+    if (file.exists())
     {
-        LLFileSystem file(uuid, type);
-        U32 size = file.getSize();
-        if (size > 0)
+       
+        if (file.getSize() > 0)
         {
             // we've already got the file
             if (callback)
@@ -503,8 +502,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
         return;
     }
 
-    BOOL exists = LLFileSystem::getExists(uuid, type);
     LLFileSystem file(uuid, type);
+    bool exists = file.exists();
     U32 size = exists ? file.getSize() : 0;
 
     if (size > 0)
@@ -523,7 +522,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
     {
         if (exists)
         {
-            LL_WARNS("AssetStorage") << "Asset vfile " << uuid << ":" << type << " found with bad size " << file.getSize() << ", removing" << LL_ENDL;
+            LL_WARNS("AssetStorage") << "Asset vfile " << uuid << ":" << type << " found with bad size " << size << ", removing" << LL_ENDL;
             file.remove();
         }
         
@@ -704,8 +703,8 @@ void LLAssetStorage::getEstateAsset(
         return;
     }
     
-    BOOL exists = LLFileSystem::getExists(asset_id, atype);
     LLFileSystem file(asset_id, atype);
+    bool exists = file.exists();
     U32 size = exists ? file.getSize() : 0;
 
     if (size > 0)
@@ -722,7 +721,7 @@ void LLAssetStorage::getEstateAsset(
     {
         if (exists)
         {
-            LL_WARNS("AssetStorage") << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << LL_ENDL;
+            LL_WARNS("AssetStorage") << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << size << ", removing" << LL_ENDL;
             file.remove();
         }
 
@@ -840,8 +839,8 @@ void LLAssetStorage::getInvItemAsset(
             return;
         }
 
-        exists = LLFileSystem::getExists(asset_id, atype);
         LLFileSystem file(asset_id, atype);
+        exists = file.exists();
         size = exists ? file.getSize() : 0;
         if(exists && size < 1)
         {
@@ -1377,27 +1376,33 @@ void LLAssetStorage::legacyGetDataCallback(const LLUUID &uuid,
          && !toxic )
     {
         LLFileSystem file(uuid, type);
+        if (file.open())
+        {
+            std::string uuid_str;
 
-        std::string uuid_str;
-
-        uuid.toString(uuid_str);
-        filename = llformat("%s.%s",gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str(),LLAssetType::lookup(type));
+            uuid.toString(uuid_str);
+            filename = llformat("%s.%s", gDirUtilp->getExpandedFilename(LL_PATH_CACHE, uuid_str).c_str(), LLAssetType::lookup(type));
 
-        LLFILE* fp = LLFile::fopen(filename, "wb");     /* Flawfinder: ignore */ 
-        if (fp)
-        {
-            const S32 buf_size = 65536;
-            U8 copy_buf[buf_size];
-            while (file.read(copy_buf, buf_size))   /* Flawfinder: ignore */
+            LLUniqueFile fp = LLFile::fopen(filename, "wb");     /* Flawfinder: ignore */
+            if (fp)
             {
-                if (fwrite(copy_buf, file.getLastBytesRead(), 1, fp) < 1)
+                const S32 buf_size = 65536;
+                U8 copy_buf[buf_size];
+                while (file.read(copy_buf, buf_size))   /* Flawfinder: ignore */
                 {
-                    // return a bad file error if we can't write the whole thing
-                    status = LL_ERR_CANNOT_OPEN_FILE;
+                    if (fwrite(copy_buf, file.getLastBytesRead(), 1, fp) < 1)
+                    {
+                        // return a bad file error if we can't write the whole thing
+                        status = LL_ERR_CANNOT_OPEN_FILE;
+                    }
                 }
-            }
 
-            fclose(fp);
+                fp.close();
+            }
+            else
+            {
+                status = LL_ERR_CANNOT_OPEN_FILE;
+            }
         }
         else
         {
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index c4d9e881825..20fdb33c03c 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -795,14 +795,16 @@ LLSD HttpCoroutineAdapter::postFileAndSuspend(LLCore::HttpRequest::ptr_t request
     {
         LLCore::BufferArrayStream outs(fileData.get());
         LLFileSystem vfile(assetId, assetType, LLFileSystem::READ);
-
-        S32 fileSize = vfile.getSize();
-        U8* fileBuffer;
-        fileBuffer = new U8[fileSize];
-        vfile.read(fileBuffer, fileSize);
-        
-        outs.write((char*)fileBuffer, fileSize);
-        delete[] fileBuffer;
+        if (vfile.open())
+        {
+            S32 fileSize = vfile.getSize();
+            U8* fileBuffer = new U8[fileSize];
+            if (vfile.read(fileBuffer, fileSize))
+            {
+                outs.write((char*)fileBuffer, fileSize);
+            }
+            delete[] fileBuffer;
+        }
     }
 
     return postAndSuspend(request, url, fileData, options, headers);
diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp
index 027283232dd..340d4e88b03 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -101,7 +101,7 @@ LLTSCode LLTransferSourceAsset::dataCallback(const S32 packet_id,
 
 	LLFileSystem vf(mParams.getAssetID(), mParams.getAssetType(), LLFileSystem::READ);
 
-	if (!vf.getSize())
+	if (!vf.open() || !vf.getSize())
 	{
 		// Something bad happened with the asset request!
 		return LLTS_ERROR;
diff --git a/indra/llmessage/lltransfertargetvfile.cpp b/indra/llmessage/lltransfertargetvfile.cpp
index f6faadf87fc..4c2c86344f3 100644
--- a/indra/llmessage/lltransfertargetvfile.cpp
+++ b/indra/llmessage/lltransfertargetvfile.cpp
@@ -149,7 +149,7 @@ LLTSCode LLTransferTargetVFile::dataCallback(const S32 packet_id, U8 *in_datap,
 		return LLTS_OK;
 	}
 
-	if (!vf.write(in_datap, in_size))
+	if (!vf.open() || !vf.write(in_datap, in_size))
 	{
 		LL_WARNS() << "Failure in LLTransferTargetVFile::dataCallback!" << LL_ENDL;
 		return LLTS_ERROR;
@@ -175,8 +175,7 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status)
 	  case LLTS_DONE:
 		if (!mNeedsCreate)
 		{
-			LLFileSystem file(mTempID, mParams.getAssetType(), LLFileSystem::WRITE);
-			if (!file.rename(mParams.getAssetID(), mParams.getAssetType()))
+			if (!LLFileSystem::renameFile(mTempID, mParams.getAssetType(), mParams.getAssetID(), mParams.getAssetType()))
 			{
 				LL_ERRS() << "LLTransferTargetVFile: rename failed" << LL_ENDL;
 			}
@@ -194,8 +193,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;
-		  LLFileSystem vf(mTempID, mParams.getAssetType(), LLFileSystem::APPEND);
-		  vf.remove();
+		  LLFileSystem::removeFile(mTempID, mParams.getAssetType());
 	  }
 	  break;
 	}
diff --git a/indra/llmessage/llxfer_vfile.cpp b/indra/llmessage/llxfer_vfile.cpp
index 12419b342df..0a1973a3668 100644
--- a/indra/llmessage/llxfer_vfile.cpp
+++ b/indra/llmessage/llxfer_vfile.cpp
@@ -79,9 +79,9 @@ void LLXfer_VFile::cleanup ()
 	if (mTempID.notNull() &&
 		mDeleteTempFile)
 	{
-		if (LLFileSystem::getExists(mTempID, mType))
+		LLFileSystem file(mTempID, mType);
+		if (file.exists())
 		{
-			LLFileSystem file(mTempID, mType, LLFileSystem::WRITE);
 			file.remove();
 		}
 		else
@@ -91,8 +91,7 @@ void LLXfer_VFile::cleanup ()
 		}
 	}
 
-	delete mVFile;
-	mVFile = NULL;
+	mVFile.reset();
 
 	LLXfer::cleanup();
 }
@@ -185,18 +184,25 @@ S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host)
 	mBufferLength = 0;
 	mBufferStartOffset = 0;	
 	
-	delete mVFile;
-	mVFile = NULL;
+	mVFile.reset();
+
 	if(LLFileSystem::getExists(mLocalID, mType))
 	{
-		mVFile = new LLFileSystem(mLocalID, mType, LLFileSystem::READ);
+		mVFile = std::make_unique<LLFileSystem>(mLocalID, mType, LLFileSystem::READ);
+		if (!mVFile->open())
+		{
+			LL_WARNS("Xfer") << "LLXfer_VFile::startSend() can't read cache file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL;
+			mVFile.reset();
+
+			return LL_ERR_FILE_NOT_FOUND;
+		}
+
 
 		if (mVFile->getSize() <= 0)
 		{
 			LL_WARNS("Xfer") << "LLXfer_VFile::startSend() cache file " << mLocalID << "." << LLAssetType::lookup(mType)		
 				<< " has unexpected file size of " << mVFile->getSize() << LL_ENDL;
-			delete mVFile;
-			mVFile = NULL;
+			mVFile.reset();
 
 			return LL_ERR_FILE_EMPTY;
 		}
@@ -222,8 +228,7 @@ void LLXfer_VFile::closeFileHandle()
 {
 	if (mVFile)
 	{
-		delete mVFile;
-		mVFile = NULL;
+		mVFile.reset();
 	}
 }
 
@@ -237,7 +242,12 @@ S32 LLXfer_VFile::reopenFileHandle()
 	{
 		if (LLFileSystem::getExists(mLocalID, mType))
 		{
-			mVFile = new LLFileSystem(mLocalID, mType, LLFileSystem::READ);
+			mVFile = std::make_unique<LLFileSystem>(mLocalID, mType, LLFileSystem::READ);
+			if (!mVFile->open())
+			{
+				LL_WARNS("Xfer") << "LLXfer_VFile::reopenFileHandle() can't read cache file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL;
+				retval = LL_ERR_FILE_NOT_FOUND;
+			}
 		}
 		else
 		{
@@ -315,10 +325,12 @@ S32 LLXfer_VFile::flush()
 	if (mBufferLength)
 	{
 		LLFileSystem file(mTempID, mType, LLFileSystem::APPEND);
+		if (file.open())
+		{
+			file.write((U8*)mBuffer, mBufferLength);
 
-		file.write((U8*)mBuffer, mBufferLength);
-			
-		mBufferLength = 0;
+			mBufferLength = 0;
+		}
 	}
 	return (retval);
 }
@@ -334,9 +346,9 @@ S32 LLXfer_VFile::processEOF()
 
 	if (!mCallbackResult)
 	{
-		if (LLFileSystem::getExists(mTempID, mType))
+		LLFileSystem file(mTempID, mType);
+		if (file.exists())
 		{
-			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;
@@ -356,8 +368,7 @@ S32 LLXfer_VFile::processEOF()
 
 	if (mVFile)
 	{
-		delete mVFile;
-		mVFile = NULL;
+		mVFile.reset();
 	}
 
 	retval = LLXfer::processEOF();
diff --git a/indra/llmessage/llxfer_vfile.h b/indra/llmessage/llxfer_vfile.h
index d82bab5f6c9..9225059dcf6 100644
--- a/indra/llmessage/llxfer_vfile.h
+++ b/indra/llmessage/llxfer_vfile.h
@@ -32,7 +32,7 @@
 
 class LLFileSystem;
 
-class LLXfer_VFile : public LLXfer
+class LLXfer_VFile final : public LLXfer
 {
  protected:
 	LLUUID mLocalID;
@@ -40,7 +40,7 @@ class LLXfer_VFile : public LLXfer
 	LLUUID mTempID;
 	LLAssetType::EType mType;
 	
-	LLFileSystem *mVFile;
+	std::unique_ptr<LLFileSystem> mVFile;
 
 	std::string mName;
 
diff --git a/indra/newview/alaoengine.cpp b/indra/newview/alaoengine.cpp
index 1b48047b7d1..cd7446a5232 100644
--- a/indra/newview/alaoengine.cpp
+++ b/indra/newview/alaoengine.cpp
@@ -1680,18 +1680,21 @@ void ALAOEngine::onNotecardLoadComplete(const LLUUID& assetUUID, LLAssetType::ET
 	LL_DEBUGS("AOEngine") << "Downloading import notecard complete." << LL_ENDL;
 
 	LLFileSystem file(assetUUID, type, LLFileSystem::READ);
-
-	S32 notecardSize = file.getSize();
-	auto buffer = std::make_unique<char[]>(notecardSize + 1);
-	buffer[notecardSize] = '\0';
-
-	if (file.read((U8*)buffer.get(), notecardSize) != FALSE)
-	{
-		ALAOEngine::instance().parseNotecard(std::move(buffer));
-	}
-	else
+	if (file.open())
 	{
-		ALAOEngine::instance().parseNotecard(nullptr);
+		S32 notecardSize = file.getSize();
+		auto buffer = std::make_unique<char[]>(notecardSize + 1);
+		buffer[notecardSize] = '\0';
+
+		if (file.read((U8*)buffer.get(), notecardSize) != FALSE)
+		{
+			ALAOEngine::instance().parseNotecard(std::move(buffer));
+		}
+		else
+		{
+			ALAOEngine::instance().parseNotecard(nullptr);
+		}
+		file.close();
 	}
 }
 
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index 9813156bf2b..80d7f4d59da 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -203,7 +203,11 @@ void LLFloaterAuction::onClickSnapshot(void* data)
 		tga->encode(raw);
 
 		LLFileSystem tga_file(self->mImageID, LLAssetType::AT_IMAGE_TGA, LLFileSystem::WRITE);
-		tga_file.write(tga->getData(), tga->getDataSize());
+		if (tga_file.open())
+		{
+			tga_file.write(tga->getData(), tga->getDataSize());
+			tga_file.close();
+		}
 		
 		raw->biasedScaleToPowerOfTwo(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT);
 
@@ -213,7 +217,11 @@ void LLFloaterAuction::onClickSnapshot(void* data)
 		j2c->encode(raw, 0.0f);
 
 		LLFileSystem j2c_file(self->mImageID, LLAssetType::AT_TEXTURE, LLFileSystem::WRITE);
-		j2c_file.write(j2c->getData(), j2c->getDataSize());
+		if (j2c_file.open())
+		{
+			j2c_file.write(j2c->getData(), j2c->getDataSize());
+			j2c_file.close();
+		}
 
 		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 80a49b6731c..ba975f93526 100644
--- a/indra/newview/llfloaterbvhpreview.cpp
+++ b/indra/newview/llfloaterbvhpreview.cpp
@@ -1000,8 +1000,10 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata)
 			LLFileSystem file(motionp->getID(), LLAssetType::AT_ANIMATION, LLFileSystem::APPEND);
 
 			S32 size = dp.getCurrentSize();
-			if (file.write((U8*)buffer, size))
+			if (file.open() && file.write((U8*)buffer, size))
 			{
+				file.close();
+
 				std::string name = floaterp->getChild<LLUICtrl>("name_form")->getValue().asString();
 				std::string desc = floaterp->getChild<LLUICtrl>("description_form")->getValue().asString();
 				S32 expected_upload_cost = LLAgentBenefitsMgr::current().getAnimationUploadCost();
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index db3c56f6a59..ca024f8b782 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -2246,31 +2246,36 @@ void LLPanelEstateCovenant::onLoadComplete(const LLUUID& asset_uuid,
 		if(0 == status)
 		{
 			LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
-
-			S32 file_length = file.getSize();
-
-			std::vector<char> buffer(file_length+1);
-			file.read((U8*)&buffer[0], file_length);
-			// put a EOS at the end
-			buffer[file_length] = 0;
-
-			if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) )
+			if (file.open())
 			{
-				if( !panelp->mEditor->importBuffer( &buffer[0], file_length+1 ) )
-				{
-					LL_WARNS() << "Problem importing estate covenant." << LL_ENDL;
-					LLNotificationsUtil::add("ProblemImportingEstateCovenant");
-				}
-				else
+				S32 file_length = file.getSize();
+
+				std::vector<char> buffer(file_length + 1);
+				if (file.read((U8*)&buffer[0], file_length))
 				{
-					panelp->sendChangeCovenantID(asset_uuid);	
+					file.close();
+					// put a EOS at the end
+					buffer[file_length] = 0;
+
+					if ((file_length > 19) && !strncmp(&buffer[0], "Linden text version", 19))
+					{
+						if (!panelp->mEditor->importBuffer(&buffer[0], file_length + 1))
+						{
+							LL_WARNS() << "Problem importing estate covenant." << LL_ENDL;
+							LLNotificationsUtil::add("ProblemImportingEstateCovenant");
+						}
+						else
+						{
+							panelp->sendChangeCovenantID(asset_uuid);
+						}
+					}
+					else
+					{
+						// Version 0 (just text, doesn't include version number)
+						panelp->sendChangeCovenantID(asset_uuid);
+					}
 				}
 			}
-			else
-			{
-				// Version 0 (just text, doesn't include version number)
-				panelp->sendChangeCovenantID(asset_uuid);
-			}
 		}
 		else
 		{
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index dd2ab1ccd66..9047eae3a2e 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -908,7 +908,11 @@ void LLFloaterReporter::takeScreenshot(bool use_prev_screenshot)
 
 	// store in cache
     LLFileSystem j2c_file(mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType, LLFileSystem::WRITE);
-    j2c_file.write(upload_data->getData(), upload_data->getDataSize());
+	if (j2c_file.open())
+	{
+		j2c_file.write(upload_data->getData(), upload_data->getDataSize());
+		j2c_file.close();
+	}
 
 	// store in the image list so it doesn't try to fetch from the server
 	LLPointer<LLViewerFetchedTexture> image_in_list = 
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
index 0f772f712b2..56583039f5d 100644
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -1069,87 +1069,94 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid,
 	if (0 == status)
 	{
 		LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
-		S32 size = file.getSize();
+		if (file.open())
+		{
+			S32 size = file.getSize();
 
-		std::vector<char> buffer(size+1);
+			std::vector<char> buffer(size + 1);
 
-		file.read((U8*)&buffer[0], size);
-		// ensure there's a trailing NULL so strlen will work.
-		buffer[size] = '\0';
+			if (file.read((U8*)&buffer[0], size))
+			{
+				file.close();
 
-		LLMultiGesture* gesture = new LLMultiGesture();
+				// ensure there's a trailing NULL so strlen will work.
+				buffer[size] = '\0';
 
-		LLDataPackerAsciiBuffer dp(&buffer[0], size+1);
-		BOOL ok = gesture->deserialize(dp);
+				LLMultiGesture* gesture = new LLMultiGesture();
 
-		if (ok)
-		{
-			if (deactivate_similar)
-			{
-				self.deactivateSimilarGestures(gesture, item_id);
+				LLDataPackerAsciiBuffer dp(&buffer[0], size + 1);
+				BOOL ok = gesture->deserialize(dp);
 
-				// Display deactivation message if this was the last of the bunch.
-				if (self.mLoadingCount == 0
-					&& self.mDeactivateSimilarNames.length() > 0)
+				if (ok)
 				{
-					// we're done with this set of deactivations
-					LLSD args;
-					args["NAMES"] = self.mDeactivateSimilarNames;
-					LLNotificationsUtil::add("DeactivatedGesturesTrigger", args);
-				}
-			}
+					if (deactivate_similar)
+					{
+						self.deactivateSimilarGestures(gesture, item_id);
 
-			LLViewerInventoryItem* item = gInventory.getItem(item_id);
-			if(item)
-			{
-				gesture->mName = item->getName();
-			}
-			else
-			{
-				// Watch this item and set gesture name when item exists in inventory
-				self.setFetchID(item_id);
-				self.startFetch();
-			}
-			self.mActive[item_id] = gesture;
+						// Display deactivation message if this was the last of the bunch.
+						if (self.mLoadingCount == 0
+							&& self.mDeactivateSimilarNames.length() > 0)
+						{
+							// we're done with this set of deactivations
+							LLSD args;
+							args["NAMES"] = self.mDeactivateSimilarNames;
+							LLNotificationsUtil::add("DeactivatedGesturesTrigger", args);
+						}
+					}
 
-			// Everything has been successful.  Add to the active list.
-			gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+					LLViewerInventoryItem* item = gInventory.getItem(item_id);
+					if (item)
+					{
+						gesture->mName = item->getName();
+					}
+					else
+					{
+						// Watch this item and set gesture name when item exists in inventory
+						self.setFetchID(item_id);
+						self.startFetch();
+					}
+					self.mActive[item_id] = gesture;
 
-			if (inform_server)
-			{
-				// Inform the database of this change
-				LLMessageSystem* msg = gMessageSystem;
-				msg->newMessage("ActivateGestures");
-				msg->nextBlock("AgentData");
-				msg->addUUID("AgentID", gAgent.getID());
-				msg->addUUID("SessionID", gAgent.getSessionID());
-				msg->addU32("Flags", 0x0);
-				
-				msg->nextBlock("Data");
-				msg->addUUID("ItemID", item_id);
-				msg->addUUID("AssetID", asset_uuid);
-				msg->addU32("GestureFlags", 0x0);
+					// Everything has been successful.  Add to the active list.
+					gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
 
-				gAgent.sendReliableMessage();
-			}
-			callback_map_t::iterator i_cb = self.mCallbackMap.find(item_id);
-			
-			if(i_cb != self.mCallbackMap.end())
-			{
-				i_cb->second(gesture);
-				self.mCallbackMap.erase(i_cb);
-			}
+					if (inform_server)
+					{
+						// Inform the database of this change
+						LLMessageSystem* msg = gMessageSystem;
+						msg->newMessage("ActivateGestures");
+						msg->nextBlock("AgentData");
+						msg->addUUID("AgentID", gAgent.getID());
+						msg->addUUID("SessionID", gAgent.getSessionID());
+						msg->addU32("Flags", 0x0);
+
+						msg->nextBlock("Data");
+						msg->addUUID("ItemID", item_id);
+						msg->addUUID("AssetID", asset_uuid);
+						msg->addU32("GestureFlags", 0x0);
+
+						gAgent.sendReliableMessage();
+					}
+					callback_map_t::iterator i_cb = self.mCallbackMap.find(item_id);
 
-			self.notifyObservers();
-		}
-		else
-		{
-			LL_WARNS() << "Unable to load gesture" << LL_ENDL;
+					if (i_cb != self.mCallbackMap.end())
+					{
+						i_cb->second(gesture);
+						self.mCallbackMap.erase(i_cb);
+					}
 
-			self.mActive.erase(item_id);
-			
-			delete gesture;
-			gesture = NULL;
+					self.notifyObservers();
+				}
+				else
+				{
+					LL_WARNS() << "Unable to load gesture" << LL_ENDL;
+
+					self.mActive.erase(item_id);
+
+					delete gesture;
+					gesture = NULL;
+				}
+			}
 		}
 	}
 	else
diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp
index 2966ca1f109..88903e6a90d 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -126,37 +126,43 @@ void LLLandmarkList::processGetAssetReply(
 {
 	if( status == 0 )
 	{
-		LLFileSystem file(uuid, type);
-		S32 file_length = file.getSize();
-
-		std::vector<char> buffer(file_length + 1);
-		file.read( (U8*)&buffer[0], file_length);
-		buffer[ file_length ] = 0;
-
-		LLLandmark* landmark = LLLandmark::constructFromString(&buffer[0]);
-		if (landmark)
+		LLFileSystem file(uuid, type, LLFileSystem::READ);
+		if (file.open())
 		{
-			gLandmarkList.mList[ uuid ] = landmark;
-			gLandmarkList.mRequestedList.erase(uuid);
-			
-			LLVector3d pos;
-			if(!landmark->getGlobalPos(pos))
+			S32 file_length = file.getSize();
+
+			std::vector<char> buffer(file_length + 1);
+			if (file.read((U8*)&buffer[0], file_length))
 			{
-				LLUUID region_id;
-				if(landmark->getRegionID(region_id))
+				file.close();
+				buffer[file_length] = 0;
+
+				LLLandmark* landmark = LLLandmark::constructFromString(&buffer[0]);
+				if (landmark)
 				{
-					LLLandmark::requestRegionHandle(
-						gMessageSystem,
-						gAgent.getRegionHost(),
-						region_id,
-						boost::bind(&LLLandmarkList::onRegionHandle, &gLandmarkList, uuid));
-				}
+					gLandmarkList.mList[uuid] = landmark;
+					gLandmarkList.mRequestedList.erase(uuid);
 
-				// the callback will be called when we get the region handle.
-			}
-			else
-			{
-				gLandmarkList.makeCallbacks(uuid);
+					LLVector3d pos;
+					if (!landmark->getGlobalPos(pos))
+					{
+						LLUUID region_id;
+						if (landmark->getRegionID(region_id))
+						{
+							LLLandmark::requestRegionHandle(
+								gMessageSystem,
+								gAgent.getRegionHost(),
+								region_id,
+								boost::bind(&LLLandmarkList::onRegionHandle, &gLandmarkList, uuid));
+						}
+
+						// the callback will be called when we get the region handle.
+					}
+					else
+					{
+						gLandmarkList.makeCallbacks(uuid);
+					}
+				}
 			}
 		}
 	}
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index b7118010ace..21172fefb69 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1340,7 +1340,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)
 		{
 			//check cache for mesh skin info
 			LLFileSystem file(mesh_id, LLAssetType::AT_MESH, LLFileSystem::READ);
-			if (file.getSize() >= offset+size)
+			if (file.open() && file.getSize() >= offset+size)
 			{
 				U8* buffer = new(std::nothrow) U8[size];
 				if (!buffer)
@@ -1352,6 +1352,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)
 				++LLMeshRepository::sCacheReads;
 				file.seek(offset);
 				file.read(buffer, size);
+				file.close();
 
 				//make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
 				bool zero = true;
@@ -1453,7 +1454,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 		{
 			//check cache for mesh skin info
 			LLFileSystem file(mesh_id, LLAssetType::AT_MESH, LLFileSystem::READ);
-			if (file.getSize() >= offset+size)
+			if (file.open() && file.getSize() >= offset+size)
 			{
 				U8* buffer = new(std::nothrow) U8[size];
 				if (!buffer)
@@ -1466,6 +1467,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 
 				file.seek(offset);
 				file.read(buffer, size);
+				file.close();
 
 				//make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
 				bool zero = true;
@@ -1552,7 +1554,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 		{
 			//check cache for mesh physics shape info
 			LLFileSystem file(mesh_id, LLAssetType::AT_MESH, LLFileSystem::READ);
-			if (file.getSize() >= offset+size)
+			if (file.open() && file.getSize() >= offset+size)
 			{
 				LLMeshRepository::sCacheBytesRead += size;
 				++LLMeshRepository::sCacheReads;
@@ -1564,6 +1566,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 					return false;
 				}
 				file.read(buffer, size);
+				file.close();
 
 				//make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
 				bool zero = true;
@@ -1660,7 +1663,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, bool c
 			
 		S32 size = file.getSize();
 
-		if (size > 0)
+		if (size > 0 && file.open())
 		{
 			// *NOTE:  if the header size is ever more than 4KB, this will break
 			U8 buffer[MESH_HEADER_SIZE];
@@ -1668,6 +1671,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, bool c
 			LLMeshRepository::sCacheBytesRead += bytes;	
 			++LLMeshRepository::sCacheReads;
 			file.read(buffer, bytes);
+			file.close();
 			if (headerReceived(mesh_params, buffer, bytes) == MESH_OK)
 			{
 				// Found mesh in cache
@@ -1741,7 +1745,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
 
 			//check cache for mesh asset
 			LLFileSystem file(mesh_id, LLAssetType::AT_MESH, LLFileSystem::READ);
-			if (file.getSize() >= offset+size)
+			if (file.open() && file.getSize() >= offset+size)
 			{
 				U8* buffer = new(std::nothrow) U8[size];
 				if (!buffer)
@@ -1755,6 +1759,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
 				++LLMeshRepository::sCacheReads;
 				file.seek(offset);
 				file.read(buffer, size);
+				file.close();
 
 				//make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
 				bool zero = true;
@@ -3283,8 +3288,8 @@ 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);
 
-			LLFileSystem file(mesh_id, LLAssetType::AT_MESH, LLFileSystem::READ_WRITE);
-			if (file.getMaxSize() >= bytes)
+			LLFileSystem file(mesh_id, LLAssetType::AT_MESH, LLFileSystem::APPEND);
+			if (file.open() && file.getMaxSize() >= bytes)
 			{
 				LLMeshRepository::sCacheBytesWritten += data_size;
 				++LLMeshRepository::sCacheWrites;
@@ -3304,6 +3309,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
 				{
 					file.write(block, remaining);
 				}
+				file.close();
 
 			}
 		}
@@ -3362,10 +3368,11 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
 			S32 offset = mOffset;
 			S32 size = mRequestedBytes;
 
-			if (file.getSize() >= offset+size)
+			if (file.open() && file.getSize() >= offset+size)
 			{
 				file.seek(offset);
 				file.write(data, size);
+				file.close();
 				LLMeshRepository::sCacheBytesWritten += size;
 				++LLMeshRepository::sCacheWrites;
 			}
@@ -3425,12 +3432,13 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /*
 		S32 offset = mOffset;
 		S32 size = mRequestedBytes;
 
-		if (file.getSize() >= offset+size)
+		if (file.open() && file.getSize() >= offset+size)
 		{
 			LLMeshRepository::sCacheBytesWritten += size;
 			++LLMeshRepository::sCacheWrites;
 			file.seek(offset);
 			file.write(data, size);
+			file.close();
 		}
 	}
 	else
@@ -3474,12 +3482,13 @@ void LLMeshDecompositionHandler::processData(LLCore::BufferArray * /* body */, S
 		S32 offset = mOffset;
 		S32 size = mRequestedBytes;
 
-		if (file.getSize() >= offset+size)
+		if (file.open() && file.getSize() >= offset+size)
 		{
 			LLMeshRepository::sCacheBytesWritten += size;
 			++LLMeshRepository::sCacheWrites;
 			file.seek(offset);
 			file.write(data, size);
+			file.close();
 		}
 	}
 	else
@@ -3521,12 +3530,13 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * /* body */, S3
 		S32 offset = mOffset;
 		S32 size = mRequestedBytes;
 
-		if (file.getSize() >= offset+size)
+		if (file.open() && file.getSize() >= offset+size)
 		{
 			LLMeshRepository::sCacheBytesWritten += size;
 			++LLMeshRepository::sCacheWrites;
 			file.seek(offset);
 			file.write(data, size);
+			file.close();
 		}
 	}
 	else
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 61078e82102..6f4b0f120fe 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -861,37 +861,58 @@ void LLPreviewGesture::onLoadComplete(const LLUUID& asset_uuid,
 		if (0 == status)
 		{
 			LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
-			S32 size = file.getSize();
+			if (file.open())
+			{
+				S32 size = file.getSize();
 
-			std::vector<char> buffer(size+1);
-			file.read((U8*)&buffer[0], size);
-			buffer[size] = '\0';
+				std::vector<char> buffer(size + 1);
+				if (file.read((U8*)&buffer[0], size))
+				{
+					file.close();
 
-			LLMultiGesture* gesture = new LLMultiGesture();
+					buffer[size] = '\0';
 
-			LLDataPackerAsciiBuffer dp(&buffer[0], size+1);
-			BOOL ok = gesture->deserialize(dp);
+						LLMultiGesture* gesture = new LLMultiGesture();
 
-			if (ok)
-			{
-				// Everything has been successful.  Load up the UI.
-				self->loadUIFromGesture(gesture);
+						LLDataPackerAsciiBuffer dp(&buffer[0], size + 1);
+						BOOL ok = gesture->deserialize(dp);
+
+						if (ok)
+						{
+							// Everything has been successful.  Load up the UI.
+							self->loadUIFromGesture(gesture);
+
+							self->mStepList->selectFirstItem();
+
+							self->mDirty = FALSE;
+							self->refresh();
+							self->refreshFromItem(); // to update description and title
+						}
+						else
+						{
+							LL_WARNS() << "Unable to load gesture" << LL_ENDL;
+						}
 
-				self->mStepList->selectFirstItem();
+					delete gesture;
+					gesture = NULL;
 
-				self->mDirty = FALSE;
-				self->refresh();
-				self->refreshFromItem(); // to update description and title
+					self->mAssetStatus = PREVIEW_ASSET_LOADED;
+				}
+				else
+				{
+					LLDelayedGestureError::gestureFailedToLoad(*item_idp);
+
+					LL_WARNS() << "Problem loading gesture: " << status << LL_ENDL;
+					self->mAssetStatus = PREVIEW_ASSET_ERROR;
+				}
 			}
 			else
 			{
-				LL_WARNS() << "Unable to load gesture" << LL_ENDL;
-			}
+				LLDelayedGestureError::gestureFailedToLoad(*item_idp);
 
-			delete gesture;
-			gesture = NULL;
-
-			self->mAssetStatus = PREVIEW_ASSET_LOADED;
+				LL_WARNS() << "Problem loading gesture: " << status << LL_ENDL;
+				self->mAssetStatus = PREVIEW_ASSET_ERROR;
+			}
 		}
 		else
 		{
@@ -1148,13 +1169,17 @@ void LLPreviewGesture::saveIfNeeded()
             assetId = tid.makeAssetID(gAgent.getSecureSessionID());
 
             LLFileSystem file(assetId, LLAssetType::AT_GESTURE, LLFileSystem::WRITE);
-
-            S32 size = dp.getCurrentSize();
-            file.write((U8*)buffer, size);
-
-            LLLineEditor* descEditor = getChild<LLLineEditor>("desc");
-            LLSaveInfo* info = new LLSaveInfo(mItemUUID, mObjectUUID, descEditor->getText(), tid);
-            gAssetStorage->storeAssetData(tid, LLAssetType::AT_GESTURE, onSaveComplete, info, FALSE);
+			if (file.open())
+			{
+				S32 size = dp.getCurrentSize();
+				if (file.write((U8*)buffer, size))
+				{
+					file.close();
+					LLLineEditor* descEditor = getChild<LLLineEditor>("desc");
+					LLSaveInfo* info = new LLSaveInfo(mItemUUID, mObjectUUID, descEditor->getText(), tid);
+					gAssetStorage->storeAssetData(tid, LLAssetType::AT_GESTURE, onSaveComplete, info, FALSE);
+				}
+			}
         }
 
     }
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 79b979e5360..2706d9c48ab 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -369,36 +369,54 @@ void LLPreviewNotecard::onLoadComplete(const LLUUID& asset_uuid,
 		if(0 == status)
 		{
 			LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
+			if (file.open())
+			{
+				S32 file_length = file.getSize();
 
-			S32 file_length = file.getSize();
+				std::vector<char> buffer(file_length + 1);
+				if (file.read((U8*)&buffer[0], file_length))
+				{
+					file.close();
 
-			std::vector<char> buffer(file_length+1);
-			file.read((U8*)&buffer[0], file_length);
+					// put a EOS at the end
+					buffer[file_length] = 0;
 
-			// put a EOS at the end
-			buffer[file_length] = 0;
+					LLViewerTextEditor* previewEditor = preview->getChild<LLViewerTextEditor>("Notecard Editor");
 
-			
-			LLViewerTextEditor* previewEditor = preview->getChild<LLViewerTextEditor>("Notecard Editor");
+					if ((file_length > 19) && !strncmp(&buffer[0], "Linden text version", 19))
+					{
+						if (!previewEditor->importBuffer(&buffer[0], file_length + 1))
+						{
+							LL_WARNS() << "Problem importing notecard" << LL_ENDL;
+						}
+					}
+					else
+					{
+						// Version 0 (just text, doesn't include version number)
+						previewEditor->setText(LLStringExplicit(&buffer[0]));
+					}
 
-			if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) )
-			{
-				if( !previewEditor->importBuffer( &buffer[0], file_length+1 ) )
+					previewEditor->makePristine();
+					BOOL modifiable = preview->canModify(preview->mObjectID, preview->getItem());
+					preview->setEnabled(modifiable);
+					preview->syncExternal();
+					preview->mAssetStatus = PREVIEW_ASSET_LOADED;
+				}
+				else
 				{
-					LL_WARNS() << "Problem importing notecard" << LL_ENDL;
+					LLNotificationsUtil::add("NotecardMissing");
+
+					LL_WARNS() << "Problem loading notecard: " << status << LL_ENDL;
+					preview->mAssetStatus = PREVIEW_ASSET_ERROR;
 				}
 			}
 			else
 			{
-				// Version 0 (just text, doesn't include version number)
-				previewEditor->setText(LLStringExplicit(&buffer[0]));
-			}
+				LLNotificationsUtil::add("NotecardMissing");
 
-			previewEditor->makePristine();
-			BOOL modifiable = preview->canModify(preview->mObjectID, preview->getItem());
-			preview->setEnabled(modifiable);
-			preview->syncExternal();
-			preview->mAssetStatus = PREVIEW_ASSET_LOADED;
+				LL_WARNS() << "Problem loading notecard: " << status << LL_ENDL;
+				preview->mAssetStatus = PREVIEW_ASSET_ERROR;
+			}
 		}
 		else
 		{
@@ -596,19 +614,31 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem, bool sync)
                 asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
 
                 LLFileSystem file(asset_id, LLAssetType::AT_NOTECARD, LLFileSystem::WRITE);
+				if(file.open())
+				{
+					LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID,
+																	tid, copyitem);
 
-
-				LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID,
-																tid, copyitem);
-
-                S32 size = buffer.length() + 1;
-                file.write((U8*)buffer.c_str(), size);
-
-				gAssetStorage->storeAssetData(tid, LLAssetType::AT_NOTECARD,
-												&onSaveComplete,
-												(void*)info,
-												FALSE);
-				return true;
+					S32 size = buffer.length() + 1;
+					if(file.write((U8*)buffer.c_str(), size))
+					{
+						gAssetStorage->storeAssetData(tid, LLAssetType::AT_NOTECARD,
+														&onSaveComplete,
+														(void*)info,
+														FALSE);
+						return true;
+					}
+					else
+					{
+						LL_WARNS() << "Unable to write notecard to cache." << LL_ENDL;
+						return false;
+					}
+				}
+				else
+				{
+					LL_WARNS() << "Unable to open cache file for write." << LL_ENDL;
+					return false;
+				}
 			}
 			else // !gAssetStorage
 			{
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 7b296f435fb..15a2a4994b6 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -1795,43 +1795,61 @@ void LLPreviewLSL::onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType t
 	{
 		if(0 == status)
 		{
-			LLFileSystem file(asset_uuid, type);
-			S32 file_length = file.getSize();
-
-			std::vector<char> buffer(file_length+1);
-			file.read((U8*)&buffer[0], file_length);
-
-			// put a EOS at the end
-			buffer[file_length] = 0;
-			preview->mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), TRUE);
-			preview->mScriptEd->mEditor->makePristine();
-
-			std::string script_name = DEFAULT_SCRIPT_NAME;
-			LLInventoryItem* item = gInventory.getItem(*item_uuid);
-			BOOL is_modifiable = FALSE;
-			if (item)
+			LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
+			if (file.open())
 			{
-				if (!item->getName().empty())
+				S32 file_length = file.getSize();
+
+				std::vector<char> buffer(file_length + 1);
+				if (file.read((U8*)&buffer[0], file_length))
 				{
-					script_name = item->getName();
+					file.close();
+
+					// put a EOS at the end
+					buffer[file_length] = 0;
+					preview->mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), TRUE);
+					preview->mScriptEd->mEditor->makePristine();
+
+					std::string script_name = DEFAULT_SCRIPT_NAME;
+					LLInventoryItem* item = gInventory.getItem(*item_uuid);
+					BOOL is_modifiable = FALSE;
+					if (item)
+					{
+						if (!item->getName().empty())
+						{
+							script_name = item->getName();
+						}
+						if (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE))
+						{
+							is_modifiable = TRUE;
+						}
+					}
+					preview->mScriptEd->setScriptName(script_name);
+					preview->mScriptEd->setEnableEditing(is_modifiable);
+					preview->mScriptEd->setAssetID(asset_uuid);
+					preview->mAssetStatus = PREVIEW_ASSET_LOADED;
+
+// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2)
+					// Start the timer which will perform regular backup saves
+					if (!preview->isBackupRunning())
+					{
+						preview->startBackupTimer(60.0f);
+					}
+// [/SL:KB]
 				}
-				if (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE))
+				else
 				{
-					is_modifiable = TRUE;
+					LLNotificationsUtil::add("UnableToLoadScript");
+					preview->mAssetStatus = PREVIEW_ASSET_ERROR;
+					LL_WARNS() << "Problem loading script: " << status << LL_ENDL;
 				}
 			}
-			preview->mScriptEd->setScriptName(script_name);
-			preview->mScriptEd->setEnableEditing(is_modifiable);
-            preview->mScriptEd->setAssetID(asset_uuid);
-			preview->mAssetStatus = PREVIEW_ASSET_LOADED;
-
-// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2)
-			// Start the timer which will perform regular backup saves
-			if (!preview->isBackupRunning())
+			else
 			{
-				preview->startBackupTimer(60.0f);
+				LLNotificationsUtil::add("UnableToLoadScript");
+				preview->mAssetStatus = PREVIEW_ASSET_ERROR;
+				LL_WARNS() << "Problem loading script: " << status << LL_ENDL;
 			}
-// [/SL:KB]
 		}
 		else
 		{
@@ -2136,10 +2154,19 @@ void LLLiveLSLEditor::onLoadComplete(const LLUUID& asset_id,
 
 void LLLiveLSLEditor::loadScriptText(const LLUUID &uuid, LLAssetType::EType type)
 {
-	LLFileSystem file(uuid, type);
+	LLFileSystem file(uuid, type, LLFileSystem::READ);
+	if (!file.open())
+	{
+		return;
+	}
 	S32 file_length = file.getSize();
 	std::vector<char> buffer(file_length + 1);
-	file.read((U8*)&buffer[0], file_length);
+	if (!file.read((U8*)&buffer[0], file_length))
+	{
+		LL_WARNS() << "Error reading " << uuid << ":" << type << LL_ENDL;
+	}
+
+	file.close();
 
 	if (file.getLastBytesRead() != file_length ||
 		file_length <= 0)
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 8be43cfa08b..bf0e6fd1811 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -304,27 +304,43 @@ void LLSettingsVOBase::onAssetDownloadComplete(const LLUUID &asset_id, S32 statu
     if (!status)
     {
         LLFileSystem file(asset_id, LLAssetType::AT_SETTINGS, LLFileSystem::READ);
-        S32 size = file.getSize();
+        if (file.open())
+        {
+            S32 size = file.getSize();
 
-        std::string buffer(size + 1, '\0');
-        file.read((U8 *)buffer.data(), size);
+            std::string buffer(size + 1, '\0');
+            if (file.read((U8*)buffer.data(), size))
+            {
+                file.close();
 
-        std::stringstream llsdstream(buffer);
-        LLSD llsdsettings;
+                std::stringstream llsdstream(buffer);
+                LLSD llsdsettings;
 
-        if (LLSDSerialize::deserialize(llsdsettings, llsdstream, -1))
-        {
-            settings = createFromLLSD(llsdsettings);
-        }
+                if (LLSDSerialize::deserialize(llsdsettings, llsdstream, -1))
+                {
+                    settings = createFromLLSD(llsdsettings);
+                }
 
-        if (!settings)
-        {
-            status = 1;
-            LL_WARNS("SETTINGS") << "Unable to create settings object." << LL_ENDL;
+                if (!settings)
+                {
+                    status = 1;
+                    LL_WARNS("SETTINGS") << "Unable to create settings object." << LL_ENDL;
+                }
+                else
+                {
+                    settings->setAssetId(asset_id);
+                }
+            }
+            else
+            {
+                status = 1;
+                LL_WARNS("SETTINGS") << "Unable to read settings object from cache." << LL_ENDL;
+            }
         }
         else
         {
-            settings->setAssetId(asset_id);
+            status = 1;
+            LL_WARNS("SETTINGS") << "Unable to open settings object from cache." << LL_ENDL;
         }
     }
     else
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 14172168656..42eca88132f 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -1013,26 +1013,43 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
 	if (formatted->encode(scaled, 0.0f))
 	{
         LLFileSystem fmt_file(new_asset_id, LLAssetType::AT_TEXTURE, LLFileSystem::WRITE);
-        fmt_file.write(formatted->getData(), formatted->getDataSize());
-		std::string pos_string;
-		LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
-		std::string who_took_it;
-		LLAgentUI::buildFullname(who_took_it);
-		S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
-        std::string res_name = outfit_snapshot ? name : "Snapshot : " + pos_string;
-        std::string res_desc = outfit_snapshot ? "" : "Taken by " + who_took_it + " at " + pos_string;
-        LLFolderType::EType folder_type = outfit_snapshot ? LLFolderType::FT_NONE : LLFolderType::FT_SNAPSHOT_CATEGORY;
-        LLInventoryType::EType inv_type = outfit_snapshot ? LLInventoryType::IT_NONE : LLInventoryType::IT_SNAPSHOT;
-
-        LLResourceUploadInfo::ptr_t assetUploadInfo(new LLResourceUploadInfo(
-            tid, LLAssetType::AT_TEXTURE, res_name, res_desc, 0,
-            folder_type, inv_type,
-            PERM_ALL, LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
-            expected_upload_cost, !outfit_snapshot));
-
-        upload_new_resource(assetUploadInfo);
-
-		gViewerWindow->playSnapshotAnimAndSound();
+		if (fmt_file.open())
+		{
+			if (fmt_file.write(formatted->getData(), formatted->getDataSize()))
+			{
+				fmt_file.close();
+
+				std::string pos_string;
+				LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
+				std::string who_took_it;
+				LLAgentUI::buildFullname(who_took_it);
+				S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
+				std::string res_name = outfit_snapshot ? name : "Snapshot : " + pos_string;
+				std::string res_desc = outfit_snapshot ? "" : "Taken by " + who_took_it + " at " + pos_string;
+				LLFolderType::EType folder_type = outfit_snapshot ? LLFolderType::FT_NONE : LLFolderType::FT_SNAPSHOT_CATEGORY;
+				LLInventoryType::EType inv_type = outfit_snapshot ? LLInventoryType::IT_NONE : LLInventoryType::IT_SNAPSHOT;
+
+				LLResourceUploadInfo::ptr_t assetUploadInfo(new LLResourceUploadInfo(
+					tid, LLAssetType::AT_TEXTURE, res_name, res_desc, 0,
+					folder_type, inv_type,
+					PERM_ALL, LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
+					expected_upload_cost, !outfit_snapshot));
+
+				upload_new_resource(assetUploadInfo);
+
+				gViewerWindow->playSnapshotAnimAndSound();
+			}
+			else
+			{
+				LLNotificationsUtil::add("ErrorEncodingSnapshot");
+				LL_WARNS("Snapshot") << "Error writing snapshot to cache" << LL_ENDL;
+			}
+		}
+		else
+		{
+			LLNotificationsUtil::add("ErrorEncodingSnapshot");
+			LL_WARNS("Snapshot") << "Error opening snapshot cache file for write" << LL_ENDL;
+		}
 	}
 	else
 	{
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index 8e1355538c1..47601f31950 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -158,13 +158,25 @@ void LLViewerAssetStorage::storeAssetData(
     
     if (mUpstreamHost.isOk())
     {
-        if (LLFileSystem::getExists(asset_id, asset_type))
+        LLFileSystem vfile(asset_id, asset_type, LLFileSystem::READ);
+        if (vfile.exists())
         {
             // Pack data into this packet if we can fit it.
             U8 buffer[MTUBYTES];
             buffer[0] = 0;
 
-            LLFileSystem vfile(asset_id, asset_type, LLFileSystem::READ);
+            if (!vfile.open())
+            {
+                // This can happen if there's a bug in our code or if the cache has been corrupted.
+                LL_WARNS("AssetStorage") << "Failed to open cached asset. Data _should_ already be in the cache, but it's not! " << asset_id << LL_ENDL;
+
+                if (callback)
+                {
+                    callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_FAILED, LLExtStat::CACHE_CORRUPT);
+                }
+                return;
+            }
+
             S32 asset_size = vfile.getSize();
 
             LLAssetRequest *req = new LLAssetRequest(asset_id, asset_type);
@@ -285,7 +297,7 @@ void LLViewerAssetStorage::storeAssetData(
 #endif
 
     S32 size = 0;
-    LLFILE* fp = LLFile::fopen(filename, "rb");
+    LLUniqueFile fp = LLFile::fopen(filename, "rb");
     if (fp)
     {
         fseek(fp, 0, SEEK_END);
@@ -301,13 +313,18 @@ void LLViewerAssetStorage::storeAssetData(
 
         LLFileSystem file(asset_id, asset_type, LLFileSystem::APPEND);
 
-        const S32 buf_size = 65536;
-        U8 copy_buf[buf_size];
-        while ((size = (S32)fread(copy_buf, 1, buf_size, fp)))
+        if (file.open())
         {
-            file.write(copy_buf, size);
+            const S32 buf_size = 65536;
+            U8 copy_buf[buf_size];
+            while ((size = (S32)fread(copy_buf, 1, buf_size, fp)))
+            {
+                file.write(copy_buf, size);
+            }
+            file.close();
         }
-        fclose(fp);
+        fp.close();
+
 
         // if this upload fails, the caller needs to setup a new tempfile for us
         if (temp_file)
@@ -544,7 +561,7 @@ void LLViewerAssetStorage::assetRequestCoro(
             temp_id.generate();
             LLFileSystem vf(temp_id, atype, LLFileSystem::WRITE);
             req->mBytesFetched = size;
-            if (!vf.write(raw.data(),size))
+            if (!vf.open() || !vf.write(raw.data(), size))
             {
                 // TODO asset-http: handle error
                 LL_WARNS("ViewerAsset") << "Failure in vf.write()" << LL_ENDL;
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index f50223ba11e..27b6fdfc75d 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -475,11 +475,15 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
     {
         LLFileSystem file(getAssetId(), assetType, LLFileSystem::APPEND);
 
-        const S32 buf_size = 65536;
-        U8 copy_buf[buf_size];
-        while ((file_size = infile.read(copy_buf, buf_size)))
+        if (file.open())
         {
-            file.write(copy_buf, file_size);
+            const S32 buf_size = 65536;
+            U8 copy_buf[buf_size];
+            while ((file_size = infile.read(copy_buf, buf_size)))
+            {
+                file.write(copy_buf, file_size);
+            }
+            file.close();
         }
     }
     else
@@ -565,9 +569,12 @@ LLSD LLBufferedAssetUploadInfo::prepareUpload()
         generateNewAssetId();
 
     LLFileSystem file(getAssetId(), getAssetType(), LLFileSystem::WRITE);
-
-    S32 size = mContents.length() + 1;
-    file.write((U8*)mContents.c_str(), size);
+    if (file.open())
+    {
+        S32 size = mContents.length() + 1;
+        file.write((U8*)mContents.c_str(), size);
+        file.close();
+    }
 
     mStoredToCache = true;
 
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 6c75b8515ba..e128a20f75c 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -7304,36 +7304,52 @@ void onCovenantLoadComplete(const LLUUID& asset_uuid,
 	if(0 == status)
 	{
 		LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
-		
-		S32 file_length = file.getSize();
-		
-		std::vector<char> buffer(file_length+1);
-		file.read((U8*)&buffer[0], file_length);		
-		// put a EOS at the end
-		buffer[file_length] = '\0';
-		
-		if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) )
+		if (file.open())
 		{
-			LLViewerTextEditor::Params params;
-			params.name("temp");
-			params.max_text_length(file_length+1);
-			LLViewerTextEditor * editor = LLUICtrlFactory::create<LLViewerTextEditor> (params);
-			if( !editor->importBuffer( &buffer[0], file_length+1 ) )
+			S32 file_length = file.getSize();
+
+			std::vector<char> buffer(file_length + 1);
+			if (file.read((U8*)&buffer[0], file_length))
 			{
-				LL_WARNS("Messaging") << "Problem importing estate covenant." << LL_ENDL;
-				covenant_text = "Problem importing estate covenant.";
+				file.close(); // close file
+
+				// put a EOS at the end
+				buffer[file_length] = '\0';
+
+				if ((file_length > 19) && !strncmp(&buffer[0], "Linden text version", 19))
+				{
+					LLViewerTextEditor::Params params;
+					params.name("temp");
+					params.max_text_length(file_length + 1);
+					LLViewerTextEditor* editor = LLUICtrlFactory::create<LLViewerTextEditor>(params);
+					if (!editor->importBuffer(&buffer[0], file_length + 1))
+					{
+						LL_WARNS("Messaging") << "Problem importing estate covenant." << LL_ENDL;
+						covenant_text = "Problem importing estate covenant.";
+					}
+					else
+					{
+						// Version 0 (just text, doesn't include version number)
+						covenant_text = editor->getText();
+					}
+					delete editor;
+				}
+				else
+				{
+					LL_WARNS("Messaging") << "Problem importing estate covenant: Covenant file format error." << LL_ENDL;
+					covenant_text = "Problem importing estate covenant: Covenant file format error.";
+				}
 			}
 			else
 			{
-				// Version 0 (just text, doesn't include version number)
-				covenant_text = editor->getText();
+				LL_WARNS("Messaging") << "Problem importing estate covenant: Asset read error." << LL_ENDL;
+				covenant_text = "Problem importing estate covenant: Asset read error.";
 			}
-			delete editor;
 		}
 		else
 		{
-			LL_WARNS("Messaging") << "Problem importing estate covenant: Covenant file format error." << LL_ENDL;
-			covenant_text = "Problem importing estate covenant: Covenant file format error.";
+			LL_WARNS("Messaging") << "Problem importing estate covenant: Asset load error." << LL_ENDL;
+			covenant_text = "Problem importing estate covenant: Asset load error.";
 		}
 	}
 	else
-- 
GitLab