From db970c1a5f4737d1d6c7c6dbb50a16ec7592e6d6 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 21 Aug 2018 19:23:33 -0400
Subject: Don't compare rbegin() iterators, use LLStringUtil::endsWith().

I think the intention of (sDumpDir.rbegin() == mDirDelimiter.rbegin()) was to
test whether sDumpDir endsWith(mDirDelimiter). But those iterators will never
be equal. Instead, use LLStringUtil::endsWith().
---
 indra/llvfs/lldir.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index 2069888774..18836e54b0 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -42,6 +42,7 @@
 
 #include "lldiriterator.h"
 #include "stringize.h"
+#include "llstring.h"
 #include <boost/filesystem.hpp>
 #include <boost/foreach.hpp>
 #include <boost/range/begin.hpp>
@@ -317,9 +318,9 @@ const std::string& LLDir::getChatLogsDir() const
 void LLDir::setDumpDir( const std::string& path )
 {
     LLDir::sDumpDir = path;
-    if (! sDumpDir.empty() && sDumpDir.rbegin() == mDirDelimiter.rbegin() )
+    if (LLStringUtil::endsWith(sDumpDir, mDirDelimiter))
     {
-        sDumpDir.erase(sDumpDir.size() -1);
+        sDumpDir.erase(sDumpDir.size() - mDirDelimiter.size());
     }
 }
 
-- 
cgit v1.2.3


From 49c483eeb350f3620f26ce933007c3d4e9f66d4f Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 5 Sep 2018 18:07:35 -0400
Subject: add more block structure to TeamCity log output for components

---
 indra/llvfs/CMakeLists.txt | 1 +
 1 file changed, 1 insertion(+)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
index 67dce8c073..a9d602d333 100644
--- a/indra/llvfs/CMakeLists.txt
+++ b/indra/llvfs/CMakeLists.txt
@@ -64,6 +64,7 @@ set_source_files_properties(${llvfs_HEADER_FILES}
 list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES})
 
 add_library (llvfs ${llvfs_SOURCE_FILES})
+buildscripts_block(llvfs)
 
 set(vfs_BOOST_LIBRARIES
     ${BOOST_FILESYSTEM_LIBRARY}
-- 
cgit v1.2.3


From 9fd463bd9496ba5d97abec6ee75b9c0c089aa69d Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Fri, 7 Sep 2018 09:13:57 -0400
Subject: remove only-partially-successful attempt to put teamcity blocks
 around targets

---
 indra/llvfs/CMakeLists.txt | 1 -
 1 file changed, 1 deletion(-)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
index a9d602d333..67dce8c073 100644
--- a/indra/llvfs/CMakeLists.txt
+++ b/indra/llvfs/CMakeLists.txt
@@ -64,7 +64,6 @@ set_source_files_properties(${llvfs_HEADER_FILES}
 list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES})
 
 add_library (llvfs ${llvfs_SOURCE_FILES})
-buildscripts_block(llvfs)
 
 set(vfs_BOOST_LIBRARIES
     ${BOOST_FILESYSTEM_LIBRARY}
-- 
cgit v1.2.3


From 289813994eb492d16e3af0fa30835e2b26a84ced Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 13 Sep 2018 16:20:05 -0400
Subject: DRTVWR-474: Clean up use of LLDir::getAppRODataDir(), esp. on Mac.

Clearly it's not obvious to maintainers that on the Mac, getAppRODataDir()
returns the app's Resources directory: in a number of places the code starts
with the executable directory and appends "../Resources" to find that.
---
 indra/llvfs/lldir_mac.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index 79c4362747..87dc1b9795 100644
--- a/indra/llvfs/lldir_mac.cpp
+++ b/indra/llvfs/lldir_mac.cpp
@@ -171,9 +171,9 @@ void LLDir_Mac::initAppDirs(const std::string &app_name,
 	if (!app_read_only_data_dir.empty())
 	{
 		mAppRODataDir = app_read_only_data_dir;
-		mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+		mSkinBaseDir = add(mAppRODataDir, "skins");
 	}
-	mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "../Resources", "ca-bundle.crt");
+	mCAFile = add(mAppRODataDir, "ca-bundle.crt");
 }
 
 std::string LLDir_Mac::getCurPath()
-- 
cgit v1.2.3


From 7a336f63cc77a93362f5d4fcc274d1d908ef2f63 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 5 Dec 2018 16:57:00 -0500
Subject: SL-10153: If $APPDATA isn't already good, try SHGetFolderPath().

In that case, also update $APPDATA for child processes.
---
 indra/llvfs/lldir_win32.cpp | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 9836fa28f2..3e48e086d7 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -48,10 +48,38 @@ 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; in fact the VMP makes a point of setting it properly, since
 	// Windows itself botches the job for non-ASCII usernames (MAINT-8087).
 	mOSUserDir = ll_safe_string(getenv("APPDATA"));
+	// On Windows, it's a Bad Thing if a pathname contains ASCII question
+	// marks. In our experience, it means that the original pathname contained
+	// non-ASCII characters that were munged to '?' somewhere along the way.
+	// Convert to LLWString first, though, in case one of the bytes in a
+	// non-ASCII UTF-8 string accidentally resembles '?'.
+	if (utf8string_to_wstring(mOSUserDir).find(llwchar('?')) != LLWString::npos)
+	{
+		// It is really unclear what we should do if the following call fails.
+		// We use it, among other things, to find where to put our log file!
+		if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, w_str)))
+		{
+			// But of course, only update mOSUserDir if SHGetFolderPathW() works.
+			mOSUserDir = utf16str_to_utf8str(llutf16string(w_str));
+			// Not only that: update our environment so that child processes
+			// will see a reasonable value as well. Use _putenv_s() rather
+			// than _wputenv_s() because WE want to control the encoding with
+			// which APPDATA is passed to child processes, instead of letting
+			// somebody else pick it.
+			_putenv_s("APPDATA", mOSUserDir.c_str());
+			// SL-10153: It is really tempting to make the above _putenv_s()
+			// call unconditional, since we've observed cases in which the
+			// parent viewer receives a valid non-ASCII APPDATA value while
+			// the child SLVersionChecker process receives one containing
+			// question marks. But if what we see is already valid, what do we
+			// gain by storing it again?
+		}
+	}
 
 	// We want cache files to go on the local disk, even if the
 	// user is on a network with a "roaming profile".
@@ -63,7 +91,6 @@ LLDir_Win32::LLDir_Win32()
 	// cleans up that version on upgrade.  JC
 	mOSCacheDir = ll_safe_string(getenv("LOCALAPPDATA"));
 
-	WCHAR w_str[MAX_PATH];
 	if (GetTempPath(MAX_PATH, w_str))
 	{
 		if (wcslen(w_str))	/* Flawfinder: ignore */ 
-- 
cgit v1.2.3


From 758e7e8df753a9b63782ff2964c26c0b0a4015fe Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 6 Dec 2018 14:33:51 -0500
Subject: SL-10174: LOCALAPPDATA bad? Try SHGetFolderPath(CSIDL_LOCAL_APPDATA).

This logic is essentially copy-and-edited from the same suspenders-and-belt
concerning APPDATA and CSIDL_APPDATA for SL-10153.
---
 indra/llvfs/lldir_win32.cpp | 13 +++++++++++++
 1 file changed, 13 insertions(+)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 3e48e086d7..f972f27fd0 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -90,6 +90,19 @@ LLDir_Win32::LLDir_Win32()
 	// We used to store the cache in AppData\Roaming, and the installer
 	// cleans up that version on upgrade.  JC
 	mOSCacheDir = ll_safe_string(getenv("LOCALAPPDATA"));
+	// Windows really does not deal well with pathnames containing non-ASCII
+	// characters. See above remarks about APPDATA.
+	if (utf8string_to_wstring(mOSCacheDir).find(llwchar('?')) != LLWString::npos)
+	{
+		if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, w_str)))
+		{
+			// But of course, only update mOSCacheDir if SHGetFolderPathW() works.
+			mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str));
+			// Update our environment so that child processes will see a
+			// reasonable value as well.
+			_putenv_s("LOCALAPPDATA", mOSCacheDir.c_str());
+		}
+	}
 
 	if (GetTempPath(MAX_PATH, w_str))
 	{
-- 
cgit v1.2.3


From a36cd3a2925bf77aa804a5617e0a227cabacde46 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sat, 8 Dec 2018 10:30:18 -0500
Subject: SL-10153: Try to handle non-English non-ASCII Windows APPDATA.

---
 indra/llvfs/lldir_win32.cpp | 113 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 89 insertions(+), 24 deletions(-)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index f972f27fd0..96bd779b5f 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -31,6 +31,8 @@
 #include "lldir_win32.h"
 #include "llerror.h"
 #include "llrand.h"		// for gLindenLabRandomNumber
+#include "stringize.h"
+#include "llfile.h"
 #include <shlobj.h>
 #include <fstream>
 
@@ -43,6 +45,48 @@
 #define PACKVERSION(major,minor) MAKELONG(minor,major)
 DWORD GetDllVersion(LPCTSTR lpszDllName);
 
+namespace
+{ // anonymous
+    enum class prst { INIT, OPEN, SKIP } state;
+    llofstream prelogf;
+
+    void prelog(const std::string& message)
+    {
+        switch (state)
+        {
+        case prst::INIT:
+            // assume we failed, until we succeed
+            state = prst::SKIP;
+
+            // can't initialize within one case of a switch statement
+            const char* prelog_name;
+            prelog_name = getenv("PRELOG");
+            if (! prelog_name)
+                // no PRELOG variable set, carry on
+                return;
+            prelogf.open(prelog_name, std::ios_base::app);
+            if (! 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
@@ -52,32 +96,38 @@ LLDir_Win32::LLDir_Win32()
 	// Application Data is where user settings go. We rely on $APPDATA being
 	// correct; in fact the VMP makes a point of setting it properly, since
 	// Windows itself botches the job for non-ASCII usernames (MAINT-8087).
-	mOSUserDir = ll_safe_string(getenv("APPDATA"));
+	// Try using wide-character getenv()??
+	wchar_t *APPDATA = _wgetenv(L"APPDATA");
+	if (APPDATA)
+	{
+		mOSUserDir = ll_convert_wide_to_string(APPDATA, CP_UTF8);
+	}
+	PRELOG("APPDATA='" << mOSUserDir << "'");
 	// On Windows, it's a Bad Thing if a pathname contains ASCII question
 	// marks. In our experience, it means that the original pathname contained
 	// non-ASCII characters that were munged to '?' somewhere along the way.
 	// Convert to LLWString first, though, in case one of the bytes in a
 	// non-ASCII UTF-8 string accidentally resembles '?'.
-	if (utf8string_to_wstring(mOSUserDir).find(llwchar('?')) != LLWString::npos)
+	// Bear in mind that llwchar is not necessarily wchar_t, therefore L'?' is
+	// not necessarily the right type.
+	if (mOSUserDir.empty() ||
+		utf8string_to_wstring(mOSUserDir).find(llwchar('?')) != LLWString::npos)
 	{
-		// It is really unclear what we should do if the following call fails.
-		// We use it, among other things, to find where to put our log file!
-		if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, w_str)))
+		PRELOG("APPDATA empty or contains ASCII '?'");
+		//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 SHGetFolderPathW() works.
-			mOSUserDir = utf16str_to_utf8str(llutf16string(w_str));
+			// But of course, only update mOSUserDir if SHGetKnownFolderPath() works.
+			mOSUserDir = ll_convert_wide_to_string(pwstr, CP_UTF8);
 			// Not only that: update our environment so that child processes
-			// will see a reasonable value as well. Use _putenv_s() rather
-			// than _wputenv_s() because WE want to control the encoding with
-			// which APPDATA is passed to child processes, instead of letting
-			// somebody else pick it.
-			_putenv_s("APPDATA", mOSUserDir.c_str());
-			// SL-10153: It is really tempting to make the above _putenv_s()
-			// call unconditional, since we've observed cases in which the
-			// parent viewer receives a valid non-ASCII APPDATA value while
-			// the child SLVersionChecker process receives one containing
-			// question marks. But if what we see is already valid, what do we
-			// gain by storing it again?
+			// will see a reasonable value as well.
+			_wputenv_s(L"APPDATA", pwstr);
+			// SHGetKnownFolderPath() contract requires us to free pwstr
+			CoTaskMemFree(pwstr);
+			PRELOG("mOSUserDir='" << mOSUserDir << "'");
 		}
 	}
 
@@ -89,18 +139,33 @@ LLDir_Win32::LLDir_Win32()
 	//
 	// We used to store the cache in AppData\Roaming, and the installer
 	// cleans up that version on upgrade.  JC
-	mOSCacheDir = ll_safe_string(getenv("LOCALAPPDATA"));
+	// Again, try using wide-character getenv().
+	wchar_t *LOCALAPPDATA = _wgetenv(L"LOCALAPPDATA");
+	if (LOCALAPPDATA)
+	{
+		mOSCacheDir = ll_convert_wide_to_string(LOCALAPPDATA, CP_UTF8);
+	}
+	PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'");
 	// Windows really does not deal well with pathnames containing non-ASCII
 	// characters. See above remarks about APPDATA.
-	if (utf8string_to_wstring(mOSCacheDir).find(llwchar('?')) != LLWString::npos)
+	if (mOSCacheDir.empty() ||
+		utf8string_to_wstring(mOSCacheDir).find(llwchar('?')) != LLWString::npos)
 	{
-		if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, w_str)))
+		PRELOG("LOCALAPPDATA empty or contains ASCII '?'");
+		//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 SHGetFolderPathW() works.
-			mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str));
+			// But of course, only update mOSCacheDir if SHGetKnownFolderPath() works.
+			mOSCacheDir = ll_convert_wide_to_string(pwstr, CP_UTF8);
 			// Update our environment so that child processes will see a
 			// reasonable value as well.
-			_putenv_s("LOCALAPPDATA", mOSCacheDir.c_str());
+			_wputenv_s(L"LOCALAPPDATA", pwstr);
+			// SHGetKnownFolderPath() contract requires us to free pwstr
+			CoTaskMemFree(pwstr);
+			PRELOG("mOSCacheDir='" << mOSCacheDir << "'");
 		}
 	}
 
-- 
cgit v1.2.3


From a4eb5056a717feaf940f125756c7521b9103d41a Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sat, 8 Dec 2018 11:26:37 -0500
Subject: SL-10153: Need ole32 for new Windows call to CoTaskMemFree().

---
 indra/llvfs/CMakeLists.txt | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
index 67dce8c073..8578f7a6bd 100644
--- a/indra/llvfs/CMakeLists.txt
+++ b/indra/llvfs/CMakeLists.txt
@@ -98,6 +98,9 @@ if (LL_TESTS)
 
     # INTEGRATION TESTS
     set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+    if (WINDOWS)
+      list(APPEND test_libs ole32)
+    endif (WINDOWS)
 
     # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
     LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}")
-- 
cgit v1.2.3


From 601cbe1f60b94ae8105329b4e4f745b36721e5aa Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sat, 8 Dec 2018 12:18:46 -0500
Subject: SL-10153: Add ole32 to WINDOWS_LIBRARIES so it's everywhere we need.

---
 indra/llvfs/CMakeLists.txt | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
index 8578f7a6bd..67dce8c073 100644
--- a/indra/llvfs/CMakeLists.txt
+++ b/indra/llvfs/CMakeLists.txt
@@ -98,9 +98,6 @@ if (LL_TESTS)
 
     # INTEGRATION TESTS
     set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
-    if (WINDOWS)
-      list(APPEND test_libs ole32)
-    endif (WINDOWS)
 
     # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
     LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}")
-- 
cgit v1.2.3


From 9479d422d4b34e2ffd08017272412ab3bd1ae00e Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 10 Dec 2018 17:14:31 -0500
Subject: SL-10153: Use a degenerate singleton for PRELOG log file.

The previous build declared a static std::ofstream; but the code that
determines the pathname for the log file is called so early that static
objects have not yet been constructed. Declare a pointer instead, and
instantiate it on demand.
---
 indra/llvfs/lldir_win32.cpp | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 96bd779b5f..e97424c9a9 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -30,7 +30,6 @@
 
 #include "lldir_win32.h"
 #include "llerror.h"
-#include "llrand.h"		// for gLindenLabRandomNumber
 #include "stringize.h"
 #include "llfile.h"
 #include <shlobj.h>
@@ -47,8 +46,10 @@ DWORD GetDllVersion(LPCTSTR lpszDllName);
 
 namespace
 { // anonymous
-    enum class prst { INIT, OPEN, SKIP } state;
-    llofstream prelogf;
+    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)
     {
@@ -64,18 +65,18 @@ namespace
             if (! prelog_name)
                 // no PRELOG variable set, carry on
                 return;
-            prelogf.open(prelog_name, std::ios_base::app);
-            if (! prelogf.is_open())
+            prelogf = new std::ofstream(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;
+            (*prelogf) << "========================================================================"
+                       << std::endl;
             // fall through, don't break
 
         case prst::OPEN:
-            prelogf << message << std::endl;
+            (*prelogf) << message << std::endl;
             break;
 
         case prst::SKIP:
-- 
cgit v1.2.3


From bb4a649b9c324e7989de6e59398c85e80fe2acc7 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 11 Dec 2018 15:47:29 -0500
Subject: SL-10153: Validate APPDATA, LOCALAPPDATA by checking existence.

---
 indra/llvfs/lldir_win32.cpp | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index e97424c9a9..fc4680bbfb 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -104,17 +104,13 @@ LLDir_Win32::LLDir_Win32()
 		mOSUserDir = ll_convert_wide_to_string(APPDATA, CP_UTF8);
 	}
 	PRELOG("APPDATA='" << mOSUserDir << "'");
-	// On Windows, it's a Bad Thing if a pathname contains ASCII question
-	// marks. In our experience, it means that the original pathname contained
-	// non-ASCII characters that were munged to '?' somewhere along the way.
-	// Convert to LLWString first, though, in case one of the bytes in a
-	// non-ASCII UTF-8 string accidentally resembles '?'.
-	// Bear in mind that llwchar is not necessarily wchar_t, therefore L'?' is
-	// not necessarily the right type.
-	if (mOSUserDir.empty() ||
-		utf8string_to_wstring(mOSUserDir).find(llwchar('?')) != LLWString::npos)
+	// 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 empty or contains ASCII '?'");
+		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);
@@ -149,10 +145,9 @@ LLDir_Win32::LLDir_Win32()
 	PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'");
 	// Windows really does not deal well with pathnames containing non-ASCII
 	// characters. See above remarks about APPDATA.
-	if (mOSCacheDir.empty() ||
-		utf8string_to_wstring(mOSCacheDir).find(llwchar('?')) != LLWString::npos)
+	if (mOSCacheDir.empty() || ! fileExists(mOSCacheDir))
 	{
-		PRELOG("LOCALAPPDATA empty or contains ASCII '?'");
+		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);
-- 
cgit v1.2.3


From c4096f670c7b3d43f8a5c1f65ef7e02033b0329d Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 14 Dec 2018 15:38:13 -0500
Subject: SL-10153: Review and rationalize fetching paths from environment.

Use LLStringUtil::getenv() or getoptenv() whenever we fetch a string that will
be used as a pathname.

Use LLFile::tmpdir() instead of getenv("TEMP").

As an added extra-special bonus, finally clean up $TMP/llcontrol-test-zzzzzz
directories that have been accumulating every time we run a local build!
---
 indra/llvfs/lldir_linux.cpp   | 33 +++++++++++-------------
 indra/llvfs/lldir_solaris.cpp | 60 +++++++++++++++++--------------------------
 indra/llvfs/lldir_win32.cpp   | 26 +++++++++----------
 3 files changed, 51 insertions(+), 68 deletions(-)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp
index 2cd06b81f8..80ad05345a 100644
--- a/indra/llvfs/lldir_linux.cpp
+++ b/indra/llvfs/lldir_linux.cpp
@@ -29,6 +29,7 @@
 #include "lldir_linux.h"
 #include "llerror.h"
 #include "llrand.h"
+#include "llstring.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -40,28 +41,24 @@ static std::string getCurrentUserHome(char* fallback)
 {
 	const uid_t uid = getuid();
 	struct passwd *pw;
-	char *result_cstr = fallback;
-	
+
 	pw = getpwuid(uid);
 	if ((pw != NULL) && (pw->pw_dir != NULL))
 	{
-		result_cstr = (char*) pw->pw_dir;
+		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_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL;
-		const char *const home_env = getenv("HOME");	/* Flawfinder: ignore */ 
-		if (home_env)
-		{
-			result_cstr = (char*) home_env;
-		}
-		else
-		{
-			LL_WARNS() << "Couldn't detect home directory!  Falling back to " << fallback << LL_ENDL;
-		}
+		LL_WARNS() << "Couldn't detect home directory!  Falling back to " << fallback << LL_ENDL;
+		return fallback;
 	}
-	
-	return std::string(result_cstr);
 }
 
 
@@ -156,18 +153,18 @@ void LLDir_Linux::initAppDirs(const std::string &app_name,
 	if (!app_read_only_data_dir.empty())
 	{
 		mAppRODataDir = app_read_only_data_dir;
-		mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+		mSkinBaseDir = add(mAppRODataDir, "skins");
 	}
 	mAppName = app_name;
 
 	std::string upper_app_name(app_name);
 	LLStringUtil::toUpper(upper_app_name);
 
-	char* app_home_env = getenv((upper_app_name + "_USER_DIR").c_str());	/* Flawfinder: ignore */ 
+	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;
+		mOSUserAppDir = *app_home_env;
 	}
 	else
 	{
diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp
index d3536a12ee..f18560ff20 100644
--- a/indra/llvfs/lldir_solaris.cpp
+++ b/indra/llvfs/lldir_solaris.cpp
@@ -29,6 +29,7 @@
 #include "lldir_solaris.h"
 #include "llerror.h"
 #include "llrand.h"
+#include "llstring.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -41,30 +42,28 @@
 
 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;
-	char *result_cstr = fallback;
-	
+
 	pw = getpwuid(uid);
 	if ((pw != NULL) && (pw->pw_dir != NULL))
 	{
-		result_cstr = (char*) pw->pw_dir;
+		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_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL;
-		const char *const home_env = getenv("HOME");	/* Flawfinder: ignore */ 
-		if (home_env)
-		{
-			result_cstr = (char*) home_env;
-		}
-		else
-		{
-			LL_WARNS() << "Couldn't detect home directory!  Falling back to " << fallback << LL_ENDL;
-		}
+		LL_WARNS() << "Couldn't detect home directory!  Falling back to " << fallback << LL_ENDL;
+		return fallback;
 	}
-	
-	return std::string(result_cstr);
 }
 
 
@@ -135,27 +134,15 @@ LLDir_Solaris::LLDir_Solaris()
 	//NOTE: Why force people to cd into the package directory?
 	//      Look for SECONDLIFE env variable and use it, if set.
 
-	char *dcf = getenv("SECONDLIFE");
-	if(dcf != NULL){
-		(void)strcpy(path, dcf);
-		(void)strcat(path, "/bin");	//NOTE:  make sure we point at the bin
-		mExecutableDir = strdup(path);
+	auto SECONDLIFE(LLDirUtil::getoptenv("SECONDLIFE"));
+	if(SECONDLIFE){
+		mExecutableDir = add(*SECONDLIFE, "bin"); //NOTE:  make sure we point at the bin
 	}else{
-			// plunk a null at last '/' to get exec dir
-		char *s = execpath + strlen(execpath) -1;
-		while(*s != '/' && s != execpath){
-			--s;
-		}
-	
-		if(s != execpath){
-			*s = (char)NULL;
-	
-			mExecutableDir = strdup(execpath);
-			LL_INFOS() << "mExecutableDir = [" << mExecutableDir << "]" << LL_ENDL;
-		}
+		mExecutableDir = getDirName(execpath);
+		LL_INFOS() << "mExecutableDir = [" << mExecutableDir << "]" << LL_ENDL;
 	}
-	
-	mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
+
+	mLLPluginDir = add(mExecutableDir, "llplugin");
 
 	// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
 	mTempDir = "/tmp";
@@ -175,17 +162,18 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name,
 	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);
 
-	char* app_home_env = getenv((upper_app_name + "_USER_DIR").c_str());	/* Flawfinder: ignore */ 
+	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;
+		mOSUserAppDir = *app_home_env;
 	}
 	else
 	{
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index fc4680bbfb..acf734f16b 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -30,6 +30,7 @@
 
 #include "lldir_win32.h"
 #include "llerror.h"
+#include "llstring.h"
 #include "stringize.h"
 #include "llfile.h"
 #include <shlobj.h>
@@ -55,17 +56,17 @@ namespace
     {
         switch (state)
         {
+            boost::optional<std::string> prelog_name;
+
         case prst::INIT:
             // assume we failed, until we succeed
             state = prst::SKIP;
 
-            // can't initialize within one case of a switch statement
-            const char* prelog_name;
-            prelog_name = getenv("PRELOG");
+            prelog_name = LLDirUtil::getoptenv("PRELOG");
             if (! prelog_name)
                 // no PRELOG variable set, carry on
                 return;
-            prelogf = new std::ofstream(prelog_name, std::ios_base::app);
+            prelogf = new llofstream(*prelog_name, std::ios_base::app);
             if (! (prelogf && prelogf->is_open()))
                 // can't complain to anybody; how?
                 return;
@@ -95,13 +96,11 @@ LLDir_Win32::LLDir_Win32()
 
 	WCHAR w_str[MAX_PATH];
 	// Application Data is where user settings go. We rely on $APPDATA being
-	// correct; in fact the VMP makes a point of setting it properly, since
-	// Windows itself botches the job for non-ASCII usernames (MAINT-8087).
-	// Try using wide-character getenv()??
-	wchar_t *APPDATA = _wgetenv(L"APPDATA");
+	// correct.
+	auto APPDATA = LLStringUtil::getoptenv("APPDATA");
 	if (APPDATA)
 	{
-		mOSUserDir = ll_convert_wide_to_string(APPDATA, CP_UTF8);
+		mOSUserDir = *APPDATA;
 	}
 	PRELOG("APPDATA='" << mOSUserDir << "'");
 	// On Windows, we could have received a plain-ASCII pathname in which
@@ -118,7 +117,7 @@ LLDir_Win32::LLDir_Win32()
 		if (SUCCEEDED(okay) && pwstr)
 		{
 			// But of course, only update mOSUserDir if SHGetKnownFolderPath() works.
-			mOSUserDir = ll_convert_wide_to_string(pwstr, CP_UTF8);
+			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);
@@ -136,11 +135,10 @@ LLDir_Win32::LLDir_Win32()
 	//
 	// We used to store the cache in AppData\Roaming, and the installer
 	// cleans up that version on upgrade.  JC
-	// Again, try using wide-character getenv().
-	wchar_t *LOCALAPPDATA = _wgetenv(L"LOCALAPPDATA");
+	auto LOCALAPPDATA = LLStringUtil::getoptenv("LOCALAPPDATA");
 	if (LOCALAPPDATA)
 	{
-		mOSCacheDir = ll_convert_wide_to_string(LOCALAPPDATA, CP_UTF8);
+		mOSCacheDir = *LOCALAPPDATA;
 	}
 	PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'");
 	// Windows really does not deal well with pathnames containing non-ASCII
@@ -155,7 +153,7 @@ LLDir_Win32::LLDir_Win32()
 		if (SUCCEEDED(okay) && pwstr)
 		{
 			// But of course, only update mOSCacheDir if SHGetKnownFolderPath() works.
-			mOSCacheDir = ll_convert_wide_to_string(pwstr, CP_UTF8);
+			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);
-- 
cgit v1.2.3


From 4a136572857fcf5d5fd21789a777bbde67c1076d Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sat, 15 Dec 2018 09:13:24 -0500
Subject: SL-10153: auto name{expression} declares an initializer_list instead
 of a variable of type decltype(expression).

Using SHGetKnownFolderPath(FOLDERID_Fonts) in LLFontGL::getFontPathSystem()
requires new Windows #include files.

A variable with a constructor can't be declared within the braces of a switch
statement, even outside any of its case clauses.
---
 indra/llvfs/lldir_win32.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra/llvfs')

diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index acf734f16b..b3b3afb37e 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -54,15 +54,15 @@ namespace
 
     void prelog(const std::string& message)
     {
+        boost::optional<std::string> prelog_name;
+
         switch (state)
         {
-            boost::optional<std::string> prelog_name;
-
         case prst::INIT:
             // assume we failed, until we succeed
             state = prst::SKIP;
 
-            prelog_name = LLDirUtil::getoptenv("PRELOG");
+            prelog_name = LLStringUtil::getoptenv("PRELOG");
             if (! prelog_name)
                 // no PRELOG variable set, carry on
                 return;
-- 
cgit v1.2.3