From db970c1a5f4737d1d6c7c6dbb50a16ec7592e6d6 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed 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 #include #include @@ -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 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 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 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 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 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 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 #include @@ -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 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 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 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 @@ -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 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 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 #include #include @@ -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 #include #include @@ -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 @@ -55,17 +56,17 @@ namespace { switch (state) { + boost::optional 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 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 prelog_name; + switch (state) { - boost::optional 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