diff options
Diffstat (limited to 'indra/llfilesystem')
| -rw-r--r-- | indra/llfilesystem/lldir.cpp | 1509 | ||||
| -rw-r--r-- | indra/llfilesystem/lldir.h | 422 | ||||
| -rw-r--r-- | indra/llfilesystem/lldir_linux.cpp | 364 | ||||
| -rw-r--r-- | indra/llfilesystem/lldir_linux.h | 36 | ||||
| -rw-r--r-- | indra/llfilesystem/lldir_mac.cpp | 148 | ||||
| -rw-r--r-- | indra/llfilesystem/lldir_mac.h | 28 | ||||
| -rw-r--r-- | indra/llfilesystem/lldir_win32.cpp | 548 | ||||
| -rw-r--r-- | indra/llfilesystem/lldir_win32.h | 32 | ||||
| -rw-r--r-- | indra/llfilesystem/lldirguard.h | 58 | ||||
| -rw-r--r-- | indra/llfilesystem/lldiriterator.cpp | 322 | ||||
| -rw-r--r-- | indra/llfilesystem/lldiriterator.h | 82 | ||||
| -rw-r--r-- | indra/llfilesystem/lllfsthread.cpp | 278 | ||||
| -rw-r--r-- | indra/llfilesystem/lllfsthread.h | 182 | ||||
| -rw-r--r-- | indra/llfilesystem/tests/lldir_test.cpp | 398 | ||||
| -rw-r--r-- | indra/llfilesystem/tests/lldiriterator_test.cpp | 18 | 
15 files changed, 2198 insertions, 2227 deletions
| diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp index 0ba62fb698..cbf4c1ffb8 100644 --- a/indra/llfilesystem/lldir.cpp +++ b/indra/llfilesystem/lldir.cpp @@ -1,25 +1,25 @@ -/**  +/**   * @file lldir.cpp   * @brief implementation of directory utilities base class   *   * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -37,7 +37,7 @@  #include "lldir.h"  #include "llerror.h" -#include "lltimer.h"	// ms_sleep() +#include "lltimer.h"    // ms_sleep()  #include "lluuid.h"  #include "lldiriterator.h" @@ -69,29 +69,28 @@ LLDir *gDirUtilp = (LLDir *)&gDirUtil;  /// Values for findSkinnedFilenames(subdir) parameter  const char -	*LLDir::XUI      = "xui", -	*LLDir::HTML     = "html", -	*LLDir::TEXTURES = "textures", -	*LLDir::SKINBASE = ""; +    *LLDir::XUI      = "xui", +    *LLDir::TEXTURES = "textures", +    *LLDir::SKINBASE = "";  static const char* const empty = "";  std::string LLDir::sDumpDir = "";  LLDir::LLDir() -:	mAppName(""), -	mExecutablePathAndName(""), -	mExecutableFilename(""), -	mExecutableDir(""), -	mAppRODataDir(""), -	mOSUserDir(""), -	mOSUserAppDir(""), -	mLindenUserDir(""), -	mOSCacheDir(""), -	mCAFile(""), -	mTempDir(""), -	mDirDelimiter("/"), // fallback to forward slash if not overridden -	mLanguage("en"), -	mUserName("undefined") +:   mAppName(""), +    mExecutablePathAndName(""), +    mExecutableFilename(""), +    mExecutableDir(""), +    mAppRODataDir(""), +    mOSUserDir(""), +    mOSUserAppDir(""), +    mLindenUserDir(""), +    mOSCacheDir(""), +    mCAFile(""), +    mTempDir(""), +    mDirDelimiter("/"), // fallback to forward slash if not overridden +    mLanguage("en"), +    mUserName("undefined")  {  } @@ -110,7 +109,7 @@ std::vector<std::string> LLDir::getFilesInDir(const std::string &dirname)  #endif      std::vector<std::string> v; -     +      if (exists(p))      {          if (is_directory(p)) @@ -128,188 +127,188 @@ std::vector<std::string> LLDir::getFilesInDir(const std::string &dirname)          }      }      return v; -}    -             +} +  S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)  { -	S32 count = 0; -	std::string filename;  -	std::string fullpath; -	S32 result; - -	// File masks starting with "/" will match nothing, so we consider them invalid. -	if (LLStringUtil::startsWith(mask, getDirDelimiter())) -	{ -		LL_WARNS() << "Invalid file mask: " << mask << LL_ENDL; -		llassert(!"Invalid file mask"); -	} - -	LLDirIterator iter(dirname, mask); -	while (iter.next(filename)) -	{ -		fullpath = add(dirname, filename); - -		if(LLFile::isdir(fullpath)) -		{ -			// skipping directory traversal filenames -			count++; -			continue; -		} - -		S32 retry_count = 0; -		while (retry_count < 5) -		{ -			if (0 != LLFile::remove(fullpath)) -			{ -				retry_count++; -				result = errno; -				LL_WARNS() << "Problem removing " << fullpath << " - errorcode: " -						<< result << " attempt " << retry_count << LL_ENDL; - -				if(retry_count >= 5) -				{ -					LL_WARNS() << "Failed to remove " << fullpath << LL_ENDL ; -					return count ; -				} - -				ms_sleep(100); -			} -			else -			{ -				if (retry_count) -				{ -					LL_WARNS() << "Successfully removed " << fullpath << LL_ENDL; -				} -				break; -			}			 -		} -		count++; -	} -	return count; +    S32 count = 0; +    std::string filename; +    std::string fullpath; +    S32 result; + +    // File masks starting with "/" will match nothing, so we consider them invalid. +    if (LLStringUtil::startsWith(mask, getDirDelimiter())) +    { +        LL_WARNS() << "Invalid file mask: " << mask << LL_ENDL; +        llassert(!"Invalid file mask"); +    } + +    LLDirIterator iter(dirname, mask); +    while (iter.next(filename)) +    { +        fullpath = add(dirname, filename); + +        if(LLFile::isdir(fullpath)) +        { +            // skipping directory traversal filenames +            count++; +            continue; +        } + +        S32 retry_count = 0; +        while (retry_count < 5) +        { +            if (0 != LLFile::remove(fullpath)) +            { +                retry_count++; +                result = errno; +                LL_WARNS() << "Problem removing " << fullpath << " - errorcode: " +                        << result << " attempt " << retry_count << LL_ENDL; + +                if(retry_count >= 5) +                { +                    LL_WARNS() << "Failed to remove " << fullpath << LL_ENDL ; +                    return count ; +                } + +                ms_sleep(100); +            } +            else +            { +                if (retry_count) +                { +                    LL_WARNS() << "Successfully removed " << fullpath << LL_ENDL; +                } +                break; +            } +        } +        count++; +    } +    return count;  }  U32 LLDir::deleteDirAndContents(const std::string& dir_name)  {      //Removes the directory and its contents.  Returns number of files deleted. -	 -	U32 num_deleted = 0; -	try -	{ +    U32 num_deleted = 0; + +    try +    {  #ifdef LL_WINDOWS // or BOOST_WINDOWS_API -		boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name)); +        boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name));  #else -		boost::filesystem::path dir_path(dir_name); +        boost::filesystem::path dir_path(dir_name);  #endif -	   if (boost::filesystem::exists (dir_path)) -	   { -	      if (!boost::filesystem::is_empty (dir_path)) -		  {   // Directory has content -		     num_deleted = boost::filesystem::remove_all (dir_path); -		  } -		  else -		  {   // Directory is empty -		     boost::filesystem::remove (dir_path); -		  } -	   } -	} -	catch (boost::filesystem::filesystem_error &er) -	{  -		LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL; -	}  -	return num_deleted; -} - -const std::string LLDir::findFile(const std::string &filename,  -						   const std::string& searchPath1,  -						   const std::string& searchPath2,  -						   const std::string& searchPath3) const -{ -	std::vector<std::string> search_paths; -	search_paths.push_back(searchPath1); -	search_paths.push_back(searchPath2); -	search_paths.push_back(searchPath3); -	return findFile(filename, search_paths); +       if (boost::filesystem::exists (dir_path)) +       { +          if (!boost::filesystem::is_empty (dir_path)) +          {   // Directory has content +             num_deleted = boost::filesystem::remove_all (dir_path); +          } +          else +          {   // Directory is empty +             boost::filesystem::remove (dir_path); +          } +       } +    } +    catch (boost::filesystem::filesystem_error &er) +    { +        LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL; +    } +    return num_deleted; +} + +const std::string LLDir::findFile(const std::string &filename, +                           const std::string& searchPath1, +                           const std::string& searchPath2, +                           const std::string& searchPath3) const +{ +    std::vector<std::string> search_paths; +    search_paths.push_back(searchPath1); +    search_paths.push_back(searchPath2); +    search_paths.push_back(searchPath3); +    return findFile(filename, search_paths);  }  const std::string LLDir::findFile(const std::string& filename, const std::vector<std::string> search_paths) const  { -	std::vector<std::string>::const_iterator search_path_iter; -	for (search_path_iter = search_paths.begin(); -		search_path_iter != search_paths.end(); -		++search_path_iter) -	{ -		if (!search_path_iter->empty()) -		{ -			std::string filename_and_path = (*search_path_iter); -			if (!filename.empty()) -			{ -				filename_and_path += getDirDelimiter() + filename; -			} -			if (fileExists(filename_and_path)) -			{ -				return filename_and_path; -			} -		} -	} -	return ""; +    std::vector<std::string>::const_iterator search_path_iter; +    for (search_path_iter = search_paths.begin(); +        search_path_iter != search_paths.end(); +        ++search_path_iter) +    { +        if (!search_path_iter->empty()) +        { +            std::string filename_and_path = (*search_path_iter); +            if (!filename.empty()) +            { +                filename_and_path += getDirDelimiter() + filename; +            } +            if (fileExists(filename_and_path)) +            { +                return filename_and_path; +            } +        } +    } +    return "";  }  const std::string &LLDir::getExecutablePathAndName() const  { -	return mExecutablePathAndName; +    return mExecutablePathAndName;  }  const std::string &LLDir::getExecutableFilename() const  { -	return mExecutableFilename; +    return mExecutableFilename;  }  const std::string &LLDir::getExecutableDir() const  { -	return mExecutableDir; +    return mExecutableDir;  }  const std::string &LLDir::getWorkingDir() const  { -	return mWorkingDir; +    return mWorkingDir;  }  const std::string &LLDir::getAppName() const  { -	return mAppName; +    return mAppName;  }  const std::string &LLDir::getAppRODataDir() const  { -	return mAppRODataDir; +    return mAppRODataDir;  }  const std::string &LLDir::getOSUserDir() const  { -	return mOSUserDir; +    return mOSUserDir;  }  const std::string &LLDir::getOSUserAppDir() const  { -	return mOSUserAppDir; +    return mOSUserAppDir;  }  const std::string &LLDir::getLindenUserDir() const  { -	if (mLindenUserDir.empty()) -	{ -		LL_DEBUGS() << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << LL_ENDL; -	} +    if (mLindenUserDir.empty()) +    { +        LL_DEBUGS() << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << LL_ENDL; +    } -	return mLindenUserDir; +    return mLindenUserDir;  }  const std::string& LLDir::getChatLogsDir() const  { -	return mChatLogsDir; +    return mChatLogsDir;  }  void LLDir::setDumpDir( const std::string& path ) @@ -327,14 +326,14 @@ const std::string &LLDir::getDumpDir() const      {          LLUUID uid;          uid.generate(); -         +          sDumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "")                      + "dump-" + uid.asString(); -        dir_exists_or_crash(sDumpDir);   +        dir_exists_or_crash(sDumpDir);      } -	return LLDir::sDumpDir; +    return LLDir::sDumpDir;  }  bool LLDir::dumpDirExists() const @@ -344,80 +343,80 @@ bool LLDir::dumpDirExists() const  const std::string &LLDir::getPerAccountChatLogsDir() const  { -	return mPerAccountChatLogsDir; +    return mPerAccountChatLogsDir;  }  const std::string &LLDir::getTempDir() const  { -	return mTempDir; +    return mTempDir;  }  const std::string  LLDir::getCacheDir(bool get_default) const  { -	if (mCacheDir.empty() || get_default) -	{ -		if (!mDefaultCacheDir.empty()) -		{	// Set at startup - can't set here due to const API -			return mDefaultCacheDir; -		} -		 -		std::string res = buildSLOSCacheDir(); -		return res; -	} -	else -	{ -		return mCacheDir; -	} +    if (mCacheDir.empty() || get_default) +    { +        if (!mDefaultCacheDir.empty()) +        {   // Set at startup - can't set here due to const API +            return mDefaultCacheDir; +        } + +        std::string res = buildSLOSCacheDir(); +        return res; +    } +    else +    { +        return mCacheDir; +    }  }  // Return the default cache directory  std::string LLDir::buildSLOSCacheDir() const  { -	std::string res; -	if (getOSCacheDir().empty()) -	{ -		if (getOSUserAppDir().empty()) -		{ -			res = "data"; -		} -		else -		{ -			res = add(getOSUserAppDir(), "cache"); -		} -	} -	else -	{ -		res = add(getOSCacheDir(), "SecondLife"); -	} -	return res; +    std::string res; +    if (getOSCacheDir().empty()) +    { +        if (getOSUserAppDir().empty()) +        { +            res = "data"; +        } +        else +        { +            res = add(getOSUserAppDir(), "cache"); +        } +    } +    else +    { +        res = add(getOSCacheDir(), "SecondLife"); +    } +    return res;  }  const std::string &LLDir::getOSCacheDir() const  { -	return mOSCacheDir; +    return mOSCacheDir;  }  const std::string &LLDir::getCAFile() const  { -	return mCAFile; +    return mCAFile;  }  const std::string &LLDir::getDirDelimiter() const  { -	return mDirDelimiter; +    return mDirDelimiter;  }  const std::string& LLDir::getDefaultSkinDir() const  { -	return mDefaultSkinDir; +    return mDefaultSkinDir;  }  const std::string &LLDir::getSkinDir() const  { -	return mSkinDir; +    return mSkinDir;  }  const std::string &LLDir::getUserDefaultSkinDir() const @@ -427,258 +426,258 @@ const std::string &LLDir::getUserDefaultSkinDir() const  const std::string &LLDir::getUserSkinDir() const  { -	return mUserSkinDir; +    return mUserSkinDir;  }  const std::string LLDir::getSkinBaseDir() const  { -	return mSkinBaseDir; +    return mSkinBaseDir;  }  const std::string &LLDir::getLLPluginDir() const  { -	return mLLPluginDir; +    return mLLPluginDir;  }  const std::string &LLDir::getUserName() const  { -	return mUserName; +    return mUserName;  }  static std::string ELLPathToString(ELLPath location)  { -	typedef std::map<ELLPath, const char*> ELLPathMap; +    typedef std::map<ELLPath, const char*> ELLPathMap;  #define ENT(symbol) (symbol, #symbol) -	static const ELLPathMap sMap = map_list_of -		ENT(LL_PATH_NONE) -		ENT(LL_PATH_USER_SETTINGS) -		ENT(LL_PATH_APP_SETTINGS) -		ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet -		ENT(LL_PATH_CACHE) -		ENT(LL_PATH_CHARACTER) -		ENT(LL_PATH_HELP) -		ENT(LL_PATH_LOGS) -		ENT(LL_PATH_TEMP) -		ENT(LL_PATH_SKINS) -		ENT(LL_PATH_TOP_SKIN) -		ENT(LL_PATH_CHAT_LOGS) -		ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS) -		ENT(LL_PATH_USER_SKIN) -		ENT(LL_PATH_LOCAL_ASSETS) -		ENT(LL_PATH_EXECUTABLE) -		ENT(LL_PATH_DEFAULT_SKIN) -		ENT(LL_PATH_FONTS) -		ENT(LL_PATH_LAST) -	; +    static const ELLPathMap sMap = map_list_of +        ENT(LL_PATH_NONE) +        ENT(LL_PATH_USER_SETTINGS) +        ENT(LL_PATH_APP_SETTINGS) +        ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet +        ENT(LL_PATH_CACHE) +        ENT(LL_PATH_CHARACTER) +        ENT(LL_PATH_HELP) +        ENT(LL_PATH_LOGS) +        ENT(LL_PATH_TEMP) +        ENT(LL_PATH_SKINS) +        ENT(LL_PATH_TOP_SKIN) +        ENT(LL_PATH_CHAT_LOGS) +        ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS) +        ENT(LL_PATH_USER_SKIN) +        ENT(LL_PATH_LOCAL_ASSETS) +        ENT(LL_PATH_EXECUTABLE) +        ENT(LL_PATH_DEFAULT_SKIN) +        ENT(LL_PATH_FONTS) +        ENT(LL_PATH_LAST) +    ;  #undef ENT -	ELLPathMap::const_iterator found = sMap.find(location); -	if (found != sMap.end()) -		return found->second; -	return STRINGIZE("Invalid ELLPath value " << location); +    ELLPathMap::const_iterator found = sMap.find(location); +    if (found != sMap.end()) +        return found->second; +    return STRINGIZE("Invalid ELLPath value " << location);  }  std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const  { -	return getExpandedFilename(location, "", filename); +    return getExpandedFilename(location, "", filename);  }  std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir, const std::string& filename) const  { -	return getExpandedFilename(location, "", subdir, filename); +    return getExpandedFilename(location, "", subdir, filename);  }  std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir1, const std::string& subdir2, const std::string& in_filename) const  { -	std::string prefix; -	switch (location) -	{ -	case LL_PATH_NONE: -		// Do nothing -		break; - -	case LL_PATH_APP_SETTINGS: -		prefix = add(getAppRODataDir(), "app_settings"); -		break; -	 -	case LL_PATH_CHARACTER: -		prefix = add(getAppRODataDir(), "character"); -		break; -		 -	case LL_PATH_HELP: -		prefix = "help"; -		break; -		 -	case LL_PATH_CACHE: -		prefix = getCacheDir(); -		break; -		 +    std::string prefix; +    switch (location) +    { +    case LL_PATH_NONE: +        // Do nothing +        break; + +    case LL_PATH_APP_SETTINGS: +        prefix = add(getAppRODataDir(), "app_settings"); +        break; + +    case LL_PATH_CHARACTER: +        prefix = add(getAppRODataDir(), "character"); +        break; + +    case LL_PATH_HELP: +        prefix = "help"; +        break; + +    case LL_PATH_CACHE: +        prefix = getCacheDir(); +        break; +      case LL_PATH_DUMP:          prefix=getDumpDir();          break; -             -	case LL_PATH_USER_SETTINGS: -		prefix = add(getOSUserAppDir(), "user_settings"); -		break; - -	case LL_PATH_PER_SL_ACCOUNT: -		prefix = getLindenUserDir(); -		if (prefix.empty()) -		{ -			// if we're asking for the per-SL-account directory but we haven't -			// logged in yet (or otherwise don't know the account name from -			// which to build this string), then intentionally return a blank -			// string to the caller and skip the below warning about a blank -			// prefix. -			LL_DEBUGS("LLDir") << "getLindenUserDir() not yet set: " -							   << ELLPathToString(location) -							   << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename -							   << "' => ''" << LL_ENDL; -			return std::string(); -		} -		break; -		 -	case LL_PATH_CHAT_LOGS: -		prefix = getChatLogsDir(); -		break; -		 -	case LL_PATH_PER_ACCOUNT_CHAT_LOGS: -		prefix = getPerAccountChatLogsDir(); -		if (prefix.empty()) -		{ -			// potentially directory was not set yet -			// intentionally return a blank string to the caller -			LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL; -			return std::string(); -		} -		break; - -	case LL_PATH_LOGS: -		prefix = add(getOSUserAppDir(), "logs"); -		break; - -	case LL_PATH_TEMP: -		prefix = getTempDir(); -		break; - -	case LL_PATH_TOP_SKIN: -		prefix = getSkinDir(); -		break; - -	case LL_PATH_DEFAULT_SKIN: -		prefix = getDefaultSkinDir(); -		break; - -	case LL_PATH_USER_SKIN: -		prefix = getUserSkinDir(); -		break; - -	case LL_PATH_SKINS: -		prefix = getSkinBaseDir(); -		break; - -	case LL_PATH_LOCAL_ASSETS: -		prefix = add(getAppRODataDir(), "local_assets"); -		break; - -	case LL_PATH_EXECUTABLE: -		prefix = getExecutableDir(); -		break; -		 -	case LL_PATH_FONTS: -		prefix = add(getAppRODataDir(), "fonts"); -		break; -		 -	default: -		llassert(0); -	} - -	if (prefix.empty()) -	{ -		LL_WARNS() << ELLPathToString(location) -				<< ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename -				<< "': prefix is empty, possible bad filename" << LL_ENDL; -	} - -	std::string expanded_filename = add(prefix, subdir1, subdir2); -	if (expanded_filename.empty() && in_filename.empty()) -	{ -		return ""; -	} -	// Use explicit concatenation here instead of another add() call. Callers -	// passing in_filename as "" expect to obtain a pathname ending with -	// mDirSeparator so they can later directly concatenate with a specific -	// filename. A caller using add() doesn't care, but there's still code -	// loose in the system that uses std::string::operator+(). -	expanded_filename += mDirDelimiter; -	expanded_filename += in_filename; - -	LL_DEBUGS("LLDir") << ELLPathToString(location) -					   << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename -					   << "' => '" << expanded_filename << "'" << LL_ENDL; -	return expanded_filename; + +    case LL_PATH_USER_SETTINGS: +        prefix = add(getOSUserAppDir(), "user_settings"); +        break; + +    case LL_PATH_PER_SL_ACCOUNT: +        prefix = getLindenUserDir(); +        if (prefix.empty()) +        { +            // if we're asking for the per-SL-account directory but we haven't +            // logged in yet (or otherwise don't know the account name from +            // which to build this string), then intentionally return a blank +            // string to the caller and skip the below warning about a blank +            // prefix. +            LL_DEBUGS("LLDir") << "getLindenUserDir() not yet set: " +                               << ELLPathToString(location) +                               << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename +                               << "' => ''" << LL_ENDL; +            return std::string(); +        } +        break; + +    case LL_PATH_CHAT_LOGS: +        prefix = getChatLogsDir(); +        break; + +    case LL_PATH_PER_ACCOUNT_CHAT_LOGS: +        prefix = getPerAccountChatLogsDir(); +        if (prefix.empty()) +        { +            // potentially directory was not set yet +            // intentionally return a blank string to the caller +            LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL; +            return std::string(); +        } +        break; + +    case LL_PATH_LOGS: +        prefix = add(getOSUserAppDir(), "logs"); +        break; + +    case LL_PATH_TEMP: +        prefix = getTempDir(); +        break; + +    case LL_PATH_TOP_SKIN: +        prefix = getSkinDir(); +        break; + +    case LL_PATH_DEFAULT_SKIN: +        prefix = getDefaultSkinDir(); +        break; + +    case LL_PATH_USER_SKIN: +        prefix = getUserSkinDir(); +        break; + +    case LL_PATH_SKINS: +        prefix = getSkinBaseDir(); +        break; + +    case LL_PATH_LOCAL_ASSETS: +        prefix = add(getAppRODataDir(), "local_assets"); +        break; + +    case LL_PATH_EXECUTABLE: +        prefix = getExecutableDir(); +        break; + +    case LL_PATH_FONTS: +        prefix = add(getAppRODataDir(), "fonts"); +        break; + +    default: +        llassert(0); +    } + +    if (prefix.empty()) +    { +        LL_WARNS() << ELLPathToString(location) +                << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename +                << "': prefix is empty, possible bad filename" << LL_ENDL; +    } + +    std::string expanded_filename = add(prefix, subdir1, subdir2); +    if (expanded_filename.empty() && in_filename.empty()) +    { +        return ""; +    } +    // Use explicit concatenation here instead of another add() call. Callers +    // passing in_filename as "" expect to obtain a pathname ending with +    // mDirSeparator so they can later directly concatenate with a specific +    // filename. A caller using add() doesn't care, but there's still code +    // loose in the system that uses std::string::operator+(). +    expanded_filename += mDirDelimiter; +    expanded_filename += in_filename; + +    LL_DEBUGS("LLDir") << ELLPathToString(location) +                       << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename +                       << "' => '" << expanded_filename << "'" << LL_ENDL; +    return expanded_filename;  }  std::string LLDir::getBaseFileName(const std::string& filepath, bool strip_exten) const  { -	std::size_t offset = filepath.find_last_of(getDirDelimiter()); -	offset = (offset == std::string::npos) ? 0 : offset+1; -	std::string res = filepath.substr(offset, std::string::npos); -	if (strip_exten) -	{ -		offset = res.find_last_of('.'); -		if (offset != std::string::npos && -		    offset != 0) // if basename STARTS with '.', don't strip -		{ -			res = res.substr(0, offset); -		} -	} -	return res; +    std::size_t offset = filepath.find_last_of(getDirDelimiter()); +    offset = (offset == std::string::npos) ? 0 : offset+1; +    std::string res = filepath.substr(offset, std::string::npos); +    if (strip_exten) +    { +        offset = res.find_last_of('.'); +        if (offset != std::string::npos && +            offset != 0) // if basename STARTS with '.', don't strip +        { +            res = res.substr(0, offset); +        } +    } +    return res;  }  std::string LLDir::getDirName(const std::string& filepath) const  { -	std::size_t offset = filepath.find_last_of(getDirDelimiter()); -	S32 len = (offset == std::string::npos) ? 0 : offset; -	std::string dirname = filepath.substr(0, len); -	return dirname; +    std::size_t offset = filepath.find_last_of(getDirDelimiter()); +    S32 len = (offset == std::string::npos) ? 0 : offset; +    std::string dirname = filepath.substr(0, len); +    return dirname;  }  std::string LLDir::getExtension(const std::string& filepath) const  { -	if (filepath.empty()) -		return std::string(); -	std::string basename = getBaseFileName(filepath, false); -	std::size_t offset = basename.find_last_of('.'); -	std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1); -	LLStringUtil::toLower(exten); -	return exten; +    if (filepath.empty()) +        return std::string(); +    std::string basename = getBaseFileName(filepath, false); +    std::size_t offset = basename.find_last_of('.'); +    std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1); +    LLStringUtil::toLower(exten); +    return exten;  }  std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir, -											   const std::string &filename, -											   ESkinConstraint constraint) const +                                               const std::string &filename, +                                               ESkinConstraint constraint) const  { -	// This implementation is basically just as described in the declaration comments. -	std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint)); -	if (found.empty()) -	{ -		return ""; -	} -	return found.front(); +    // This implementation is basically just as described in the declaration comments. +    std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint)); +    if (found.empty()) +    { +        return ""; +    } +    return found.front();  }  std::string LLDir::findSkinnedFilename(const std::string &subdir, -									   const std::string &filename, -									   ESkinConstraint constraint) const +                                       const std::string &filename, +                                       ESkinConstraint constraint) const  { -	// This implementation is basically just as described in the declaration comments. -	std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint)); -	if (found.empty()) -	{ -		return ""; -	} -	return found.back(); +    // This implementation is basically just as described in the declaration comments. +    std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint)); +    if (found.empty()) +    { +        return ""; +    } +    return found.back();  }  // This method exists because the two code paths for @@ -687,236 +686,210 @@ std::string LLDir::findSkinnedFilename(const std::string &subdir,  // difference is in the body of the inner loop.  template <typename FUNCTION>  void LLDir::walkSearchSkinDirs(const std::string& subdir, -							   const std::vector<std::string>& subsubdirs, -							   const std::string& filename, -							   const FUNCTION& function) const -{ -	for (const std::string& skindir : mSearchSkinDirs) -	{ -		std::string subdir_path(add(skindir, subdir)); -		for (const std::string& subsubdir : subsubdirs) -		{ -			std::string full_path(add(subdir_path, subsubdir, filename)); -			if (fileExists(full_path)) -			{ -				function(subsubdir, full_path); -			} -		} -	} +                               const std::vector<std::string>& subsubdirs, +                               const std::string& filename, +                               const FUNCTION& function) const +{ +    for (const std::string& skindir : mSearchSkinDirs) +    { +        std::string subdir_path(add(skindir, subdir)); +        for (const std::string& subsubdir : subsubdirs) +        { +            std::string full_path(add(subdir_path, subsubdir, filename)); +            if (fileExists(full_path)) +            { +                function(subsubdir, full_path); +            } +        } +    }  }  // ridiculous little helper function that should go away when we can use lambda  inline void push_back(std::vector<std::string>& vector, const std::string& value)  { -	vector.push_back(value); +    vector.push_back(value);  }  typedef std::map<std::string, std::string> StringMap;  // ridiculous little helper function that should go away when we can use lambda  inline void store_in_map(StringMap& map, const std::string& key, const std::string& value)  { -	map[key] = value; +    map[key] = value;  }  std::vector<std::string> LLDir::findSkinnedFilenames(const std::string& subdir, -													 const std::string& filename, -													 ESkinConstraint constraint) const -{ -	// Recognize subdirs that have no localization. -	static const std::set<std::string> sUnlocalized = list_of -		("")                        // top-level directory not localized -		("textures")                // textures not localized -	; - -	LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename -					   << "', constraint " -					   << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS") -					   << LL_ENDL; - -	// Build results vector. -	std::vector<std::string> results; -	// Disallow filenames that may escape subdir -	if (filename.find("..") != std::string::npos) -	{ -		LL_WARNS("LLDir") << "Ignoring potentially relative filename '" << filename << "'" << LL_ENDL; -		return results; -	} - -	// Cache the default language directory for each subdir we've encountered. -	// A cache entry whose value is the empty string means "not localized, -	// don't bother checking again." -	static StringMap sLocalized; - -	// Check whether we've already discovered if this subdir is localized. -	StringMap::const_iterator found = sLocalized.find(subdir); -	if (found == sLocalized.end()) -	{ -		// We have not yet determined that. Is it one of the subdirs "known" -		// to be unlocalized? -		if (sUnlocalized.find(subdir) != sUnlocalized.end()) -		{ -			// This subdir is known to be unlocalized. Remember that. -			found = sLocalized.insert(StringMap::value_type(subdir, "")).first; -		} -		else -		{ -			// We do not recognize this subdir. Investigate. -			if (skinExists(subdir, "en")) -			{ -				// defaultSkinDir/subdir contains subdir "en". That's our -				// default language; this subdir is localized. -				found = sLocalized.insert(StringMap::value_type(subdir, "en")).first; -			} -			else if (skinExists(subdir, "en-us")) -			{ -				// defaultSkinDir/subdir contains subdir "en-us" but not "en". -				// Set as default language; this subdir is localized. -				found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first; -			} -			else -			{ -				// defaultSkinDir/subdir contains neither "en" nor "en-us". -				// Assume it's not localized. Remember that assumption. -				found = sLocalized.insert(StringMap::value_type(subdir, "")).first; -			} -		} -	} -	// Every code path above should have resulted in 'found' becoming a valid -	// iterator to an entry in sLocalized. -	llassert(found != sLocalized.end()); - -	// Now -- is this subdir localized, or not? The answer determines what -	// subdirectories we check (under subdir) for the requested filename. -	std::vector<std::string> subsubdirs; -	if (found->second.empty()) -	{ -		// subdir is not localized. filename should be located directly within it. -		subsubdirs.push_back(""); -	} -	else -	{ -		// subdir is localized, and found->second is the default language -		// directory within it. Check both the default language and the -		// current language -- if it differs from the default, of course. -		subsubdirs.push_back(found->second); -		if (mLanguage != found->second) -		{ -			subsubdirs.push_back(mLanguage); -		} -	} - -	// The process we use depends on 'constraint'. -	if (constraint != CURRENT_SKIN) // meaning ALL_SKINS -	{ -		// ALL_SKINS is simpler: just return every pathname generated by -		// walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its -		// FUNCTION the subsubdir as well as the full pathname. We just want -		// the full pathname. -		walkSearchSkinDirs(subdir, subsubdirs, filename, -						   boost::bind(push_back, boost::ref(results), _2)); -	} -	else                            // CURRENT_SKIN -	{ -		// CURRENT_SKIN turns out to be a bit of a misnomer because we might -		// still return files from two different skins. In any case, this -		// value of 'constraint' means we will return at most two paths: one -		// for the default language, one for the current language (supposing -		// those differ). -		// It is important to allow a user to override only the localization -		// for a particular file, for all viewer installs, without also -		// overriding the default-language file. -		// It is important to allow a user to override only the default- -		// language file, for all viewer installs, without also overriding the -		// applicable localization of that file. -		// Therefore, treat the default language and the current language as -		// two separate cases. For each, capture the most-specialized file -		// that exists. -		// Use a map keyed by subsubdir (i.e. language code). This allows us -		// to handle the case of a single subsubdirs entry with the same logic -		// that handles two. For every real file path generated by -		// walkSearchSkinDirs(), update the map entry for its subsubdir. -		StringMap path_for; -		walkSearchSkinDirs(subdir, subsubdirs, filename, -						   boost::bind(store_in_map, boost::ref(path_for), _1, _2)); -		// Now that we have a path for each of the default language and the -		// current language, copy them -- in proper order -- into results. -		// Don't drive this by walking the map itself: it matters that we -		// generate results in the same order as subsubdirs. -		for (const std::string& subsubdir : subsubdirs) -		{ -			StringMap::const_iterator found(path_for.find(subsubdir)); -			if (found != path_for.end()) -			{ -				results.push_back(found->second); -			} -		} -	} - -	LL_DEBUGS("LLDir") << empty; -	const char* comma = ""; -	for (const std::string& path : results) -	{ -		LL_CONT << comma << "'" << path << "'"; -		comma = ", "; -	} -	LL_CONT << LL_ENDL; - -	return results; -} - -// virtual -bool LLDir::skinExists(const std::string& subdir, const std::string& skin) const -{ -    std::string skin_path(add(getDefaultSkinDir(), subdir, skin)); -    return fileExists(skin_path); -} - -// virtual -std::string LLDir::getFileContents(const std::string& filename) const -{ -    LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ -    if (fp) +                                                     const std::string& filename, +                                                     ESkinConstraint constraint) const +{ +    // Recognize subdirs that have no localization. +    static const std::set<std::string> sUnlocalized = list_of +        ("")                        // top-level directory not localized +        ("textures")                // textures not localized +    ; + +    LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename +                       << "', constraint " +                       << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS") +                       << LL_ENDL; + +    // Build results vector. +    std::vector<std::string> results; +    // Disallow filenames that may escape subdir +    if (filename.find("..") != std::string::npos)      { -        fseek(fp, 0, SEEK_END); -        U32 length = ftell(fp); -        fseek(fp, 0, SEEK_SET); +        LL_WARNS("LLDir") << "Ignoring potentially relative filename '" << filename << "'" << LL_ENDL; +        return results; +    } + +    // Cache the default language directory for each subdir we've encountered. +    // A cache entry whose value is the empty string means "not localized, +    // don't bother checking again." +    static StringMap sLocalized; -        std::vector<char> buffer(length); -        size_t nread = fread(buffer.data(), 1, length, fp); -        fclose(fp); +    // Check whether we've already discovered if this subdir is localized. +    StringMap::const_iterator found = sLocalized.find(subdir); +    if (found == sLocalized.end()) +    { +        // We have not yet determined that. Is it one of the subdirs "known" +        // to be unlocalized? +        if (sUnlocalized.find(subdir) != sUnlocalized.end()) +        { +            // This subdir is known to be unlocalized. Remember that. +            found = sLocalized.insert(StringMap::value_type(subdir, "")).first; +        } +        else +        { +            // We do not recognize this subdir. Investigate. +            std::string subdir_path(add(getDefaultSkinDir(), subdir)); +            if (fileExists(add(subdir_path, "en"))) +            { +                // defaultSkinDir/subdir contains subdir "en". That's our +                // default language; this subdir is localized. +                found = sLocalized.insert(StringMap::value_type(subdir, "en")).first; +            } +            else if (fileExists(add(subdir_path, "en-us"))) +            { +                // defaultSkinDir/subdir contains subdir "en-us" but not "en". +                // Set as default language; this subdir is localized. +                found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first; +            } +            else +            { +                // defaultSkinDir/subdir contains neither "en" nor "en-us". +                // Assume it's not localized. Remember that assumption. +                found = sLocalized.insert(StringMap::value_type(subdir, "")).first; +            } +        } +    } +    // Every code path above should have resulted in 'found' becoming a valid +    // iterator to an entry in sLocalized. +    llassert(found != sLocalized.end()); + +    // Now -- is this subdir localized, or not? The answer determines what +    // subdirectories we check (under subdir) for the requested filename. +    std::vector<std::string> subsubdirs; +    if (found->second.empty()) +    { +        // subdir is not localized. filename should be located directly within it. +        subsubdirs.push_back(""); +    } +    else +    { +        // subdir is localized, and found->second is the default language +        // directory within it. Check both the default language and the +        // current language -- if it differs from the default, of course. +        subsubdirs.push_back(found->second); +        if (mLanguage != found->second) +        { +            subsubdirs.push_back(mLanguage); +        } +    } + +    // The process we use depends on 'constraint'. +    if (constraint != CURRENT_SKIN) // meaning ALL_SKINS +    { +        // ALL_SKINS is simpler: just return every pathname generated by +        // walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its +        // FUNCTION the subsubdir as well as the full pathname. We just want +        // the full pathname. +        walkSearchSkinDirs(subdir, subsubdirs, filename, +                           boost::bind(push_back, boost::ref(results), _2)); +    } +    else                            // CURRENT_SKIN +    { +        // CURRENT_SKIN turns out to be a bit of a misnomer because we might +        // still return files from two different skins. In any case, this +        // value of 'constraint' means we will return at most two paths: one +        // for the default language, one for the current language (supposing +        // those differ). +        // It is important to allow a user to override only the localization +        // for a particular file, for all viewer installs, without also +        // overriding the default-language file. +        // It is important to allow a user to override only the default- +        // language file, for all viewer installs, without also overriding the +        // applicable localization of that file. +        // Therefore, treat the default language and the current language as +        // two separate cases. For each, capture the most-specialized file +        // that exists. +        // Use a map keyed by subsubdir (i.e. language code). This allows us +        // to handle the case of a single subsubdirs entry with the same logic +        // that handles two. For every real file path generated by +        // walkSearchSkinDirs(), update the map entry for its subsubdir. +        StringMap path_for; +        walkSearchSkinDirs(subdir, subsubdirs, filename, +                           boost::bind(store_in_map, boost::ref(path_for), _1, _2)); +        // Now that we have a path for each of the default language and the +        // current language, copy them -- in proper order -- into results. +        // Don't drive this by walking the map itself: it matters that we +        // generate results in the same order as subsubdirs. +        for (const std::string& subsubdir : subsubdirs) +        { +            StringMap::const_iterator found(path_for.find(subsubdir)); +            if (found != path_for.end()) +            { +                results.push_back(found->second); +            } +        } +    } -        return std::string(buffer.data(), nread); +    LL_DEBUGS("LLDir") << empty; +    const char* comma = ""; +    for (const std::string& path : results) +    { +        LL_CONT << comma << "'" << path << "'"; +        comma = ", ";      } +    LL_CONT << LL_ENDL; -    return LLStringUtil::null; +    return results;  }  std::string LLDir::getTempFilename() const  { -	LLUUID random_uuid; -	std::string uuid_str; +    LLUUID random_uuid; +    std::string uuid_str; -	random_uuid.generate(); -	random_uuid.toString(uuid_str); +    random_uuid.generate(); +    random_uuid.toString(uuid_str); -	return add(getTempDir(), uuid_str + ".tmp"); +    return add(getTempDir(), uuid_str + ".tmp");  }  // static  std::string LLDir::getScrubbedFileName(const std::string uncleanFileName)  { -	std::string name(uncleanFileName); -	const std::string illegalChars(getForbiddenFileChars()); -	// replace any illegal file chars with and underscore '_' -	for( unsigned int i = 0; i < illegalChars.length(); i++ ) -	{ -		int j = -1; -		while((j = name.find(illegalChars[i])) > -1) -		{ -			name[j] = '_'; -		} -	} -	return name; +    std::string name(uncleanFileName); +    const std::string illegalChars(getForbiddenFileChars()); +    // replace any illegal file chars with and underscore '_' +    for( unsigned int i = 0; i < illegalChars.length(); i++ ) +    { +        int j = -1; +        while((j = name.find(illegalChars[i])) > -1) +        { +            name[j] = '_'; +        } +    } +    return name;  }  std::string LLDir::getDumpLogsDirPath(const std::string &file_name) @@ -927,241 +900,241 @@ std::string LLDir::getDumpLogsDirPath(const std::string &file_name)  // static  std::string LLDir::getForbiddenFileChars()  { -	return "\\/:*?\"<>|"; +    return "\\/:*?\"<>|";  }  void LLDir::setLindenUserDir(const std::string &username)  { -	// if the username isn't set, that's bad -	if (!username.empty()) -	{ -		// some platforms have case-sensitive filesystems, so be -		// utterly consistent with our firstname/lastname case. -		std::string userlower(username); -		LLStringUtil::toLower(userlower); -		LLStringUtil::replaceChar(userlower, ' ', '_'); -		mLindenUserDir = add(getOSUserAppDir(), userlower); -	} -	else -	{ -		LL_ERRS() << "NULL name for LLDir::setLindenUserDir" << LL_ENDL; -	} +    // if the username isn't set, that's bad +    if (!username.empty()) +    { +        // some platforms have case-sensitive filesystems, so be +        // utterly consistent with our firstname/lastname case. +        std::string userlower(username); +        LLStringUtil::toLower(userlower); +        LLStringUtil::replaceChar(userlower, ' ', '_'); +        mLindenUserDir = add(getOSUserAppDir(), userlower); +    } +    else +    { +        LL_ERRS() << "NULL name for LLDir::setLindenUserDir" << LL_ENDL; +    } -	dumpCurrentDirectories();	 +    dumpCurrentDirectories();  }  void LLDir::setChatLogsDir(const std::string &path)  { -	if (!path.empty() ) -	{ -		mChatLogsDir = path; -	} -	else -	{ -		LL_WARNS() << "Invalid name for LLDir::setChatLogsDir" << LL_ENDL; -	} +    if (!path.empty() ) +    { +        mChatLogsDir = path; +    } +    else +    { +        LL_WARNS() << "Invalid name for LLDir::setChatLogsDir" << LL_ENDL; +    }  }  void LLDir::updatePerAccountChatLogsDir()  { -	mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName); +    mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName);  }  void LLDir::setPerAccountChatLogsDir(const std::string &username)  { -	// if both first and last aren't set, assume we're grabbing the cached dir -	if (!username.empty()) -	{ -		// some platforms have case-sensitive filesystems, so be -		// utterly consistent with our firstname/lastname case. -		std::string userlower(username); -		LLStringUtil::toLower(userlower); -		LLStringUtil::replaceChar(userlower, ' ', '_'); - -		mUserName = userlower; -		updatePerAccountChatLogsDir(); -	} -	else -	{ -		LL_ERRS() << "NULL name for LLDir::setPerAccountChatLogsDir" << LL_ENDL; -	} +    // if both first and last aren't set, assume we're grabbing the cached dir +    if (!username.empty()) +    { +        // some platforms have case-sensitive filesystems, so be +        // utterly consistent with our firstname/lastname case. +        std::string userlower(username); +        LLStringUtil::toLower(userlower); +        LLStringUtil::replaceChar(userlower, ' ', '_'); + +        mUserName = userlower; +        updatePerAccountChatLogsDir(); +    } +    else +    { +        LL_ERRS() << "NULL name for LLDir::setPerAccountChatLogsDir" << LL_ENDL; +    }  }  void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language)  { -	LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'" -					   << LL_ENDL; -	mSkinName = skin_folder; -	mLanguage = language; - -	// This method is called multiple times during viewer initialization. Each -	// time it's called, reset mSearchSkinDirs. -	mSearchSkinDirs.clear(); - -	// base skin which is used as fallback for all skinned files -	// e.g. c:\program files\secondlife\skins\default -	mDefaultSkinDir = getSkinBaseDir(); -	append(mDefaultSkinDir, "default"); -	// This is always the most general of the search skin directories. -	addSearchSkinDir(mDefaultSkinDir); - -	mSkinDir = getSkinBaseDir(); -	append(mSkinDir, skin_folder); -	// Next level of generality is a skin installed with the viewer. -	addSearchSkinDir(mSkinDir); - -	// user modifications to skins, current and default -	// e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle -	mUserSkinDir = getOSUserAppDir(); -	append(mUserSkinDir, "skins"); -	mUserDefaultSkinDir = mUserSkinDir; -	append(mUserDefaultSkinDir, "default"); -	append(mUserSkinDir, skin_folder); -	// Next level of generality is user modifications to default skin... -	addSearchSkinDir(mUserDefaultSkinDir); -	// then user-defined skins. -	addSearchSkinDir(mUserSkinDir); +    LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'" +                       << LL_ENDL; +    mSkinName = skin_folder; +    mLanguage = language; + +    // This method is called multiple times during viewer initialization. Each +    // time it's called, reset mSearchSkinDirs. +    mSearchSkinDirs.clear(); + +    // base skin which is used as fallback for all skinned files +    // e.g. c:\program files\secondlife\skins\default +    mDefaultSkinDir = getSkinBaseDir(); +    append(mDefaultSkinDir, "default"); +    // This is always the most general of the search skin directories. +    addSearchSkinDir(mDefaultSkinDir); + +    mSkinDir = getSkinBaseDir(); +    append(mSkinDir, skin_folder); +    // Next level of generality is a skin installed with the viewer. +    addSearchSkinDir(mSkinDir); + +    // user modifications to skins, current and default +    // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle +    mUserSkinDir = getOSUserAppDir(); +    append(mUserSkinDir, "skins"); +    mUserDefaultSkinDir = mUserSkinDir; +    append(mUserDefaultSkinDir, "default"); +    append(mUserSkinDir, skin_folder); +    // Next level of generality is user modifications to default skin... +    addSearchSkinDir(mUserDefaultSkinDir); +    // then user-defined skins. +    addSearchSkinDir(mUserSkinDir);  }  void LLDir::addSearchSkinDir(const std::string& skindir)  { -	if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end()) -	{ -		LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL; -		mSearchSkinDirs.push_back(skindir); -	} +    if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end()) +    { +        LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL; +        mSearchSkinDirs.push_back(skindir); +    }  }  std::string LLDir::getSkinFolder() const  { -	return mSkinName; +    return mSkinName;  }  std::string LLDir::getLanguage() const  { -	return mLanguage; +    return mLanguage;  }  bool LLDir::setCacheDir(const std::string &path)  { -	if (path.empty() ) -	{ -		// reset to default -		mCacheDir = ""; -		return true; -	} -	else -	{ -		LLFile::mkdir(path); -		std::string tempname = add(path, "temp"); -		LLFILE* file = LLFile::fopen(tempname,"wt"); -		if (file) -		{ -			fclose(file); -			LLFile::remove(tempname); -			mCacheDir = path; -			return true; -		} -		return false; -	} +    if (path.empty() ) +    { +        // reset to default +        mCacheDir = ""; +        return true; +    } +    else +    { +        LLFile::mkdir(path); +        std::string tempname = add(path, "temp"); +        LLFILE* file = LLFile::fopen(tempname,"wt"); +        if (file) +        { +            fclose(file); +            LLFile::remove(tempname); +            mCacheDir = path; +            return true; +        } +        return false; +    }  }  void LLDir::dumpCurrentDirectories(LLError::ELevel level)  { -	LL_VLOGS(level, "AppInit","Directories") << "Current Directories:" << LL_ENDL; +    LL_VLOGS(level, "AppInit","Directories") << "Current Directories:" << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  CurPath:               " << getCurPath() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  AppName:               " << getAppName() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  ExecutableFilename:    " << getExecutableFilename() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  ExecutableDir:         " << getExecutableDir() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  ExecutablePathAndName: " << getExecutablePathAndName() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  WorkingDir:            " << getWorkingDir() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  AppRODataDir:          " << getAppRODataDir() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  OSUserDir:             " << getOSUserDir() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  OSUserAppDir:          " << getOSUserAppDir() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  LindenUserDir:         " << getLindenUserDir() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  TempDir:               " << getTempDir() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  CAFile:                " << getCAFile() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  SkinBaseDir:           " << getSkinBaseDir() << LL_ENDL; -	LL_VLOGS(level, "AppInit", "Directories") << "  SkinDir:               " << getSkinDir() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  CurPath:               " << getCurPath() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  AppName:               " << getAppName() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  ExecutableFilename:    " << getExecutableFilename() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  ExecutableDir:         " << getExecutableDir() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  ExecutablePathAndName: " << getExecutablePathAndName() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  WorkingDir:            " << getWorkingDir() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  AppRODataDir:          " << getAppRODataDir() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  OSUserDir:             " << getOSUserDir() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  OSUserAppDir:          " << getOSUserAppDir() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  LindenUserDir:         " << getLindenUserDir() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  TempDir:               " << getTempDir() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  CAFile:                " << getCAFile() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  SkinBaseDir:           " << getSkinBaseDir() << LL_ENDL; +    LL_VLOGS(level, "AppInit", "Directories") << "  SkinDir:               " << getSkinDir() << LL_ENDL;  }  void LLDir::append(std::string& destpath, const std::string& name) const  { -	// Delegate question of whether we need a separator to helper method. -	SepOff sepoff(needSep(destpath, name)); -	if (sepoff.first)               // do we need a separator? -	{ -		destpath += mDirDelimiter; -	} -	// If destpath ends with a separator, AND name starts with one, skip -	// name's leading separator. -	destpath += name.substr(sepoff.second); +    // Delegate question of whether we need a separator to helper method. +    SepOff sepoff(needSep(destpath, name)); +    if (sepoff.first)               // do we need a separator? +    { +        destpath += mDirDelimiter; +    } +    // If destpath ends with a separator, AND name starts with one, skip +    // name's leading separator. +    destpath += name.substr(sepoff.second);  }  LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) const  { -	if (path.empty() || name.empty()) -	{ -		// If either path or name are empty, we do not need a separator -		// between them. -		return SepOff(false, 0); -	} -	// Here we know path and name are both non-empty. But if path already ends -	// with a separator, or if name already starts with a separator, we need -	// not add one. -	std::string::size_type seplen(mDirDelimiter.length()); -	bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter); -	bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter); -	if ((! path_ends_sep) && (! name_starts_sep)) -	{ -		// If neither path nor name brings a separator to the junction, then -		// we need one. -		return SepOff(true, 0); -	} -	if (path_ends_sep && name_starts_sep) -	{ -		// But if BOTH path and name bring a separator, we need not add one. -		// Moreover, we should actually skip the leading separator of 'name'. -		return SepOff(false, (unsigned short)seplen); -	} -	// Here we know that either path_ends_sep or name_starts_sep is true -- -	// but not both. So don't add a separator, and don't skip any characters: -	// simple concatenation will do the trick. -	return SepOff(false, 0); +    if (path.empty() || name.empty()) +    { +        // If either path or name are empty, we do not need a separator +        // between them. +        return SepOff(false, 0); +    } +    // Here we know path and name are both non-empty. But if path already ends +    // with a separator, or if name already starts with a separator, we need +    // not add one. +    std::string::size_type seplen(mDirDelimiter.length()); +    bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter); +    bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter); +    if ((! path_ends_sep) && (! name_starts_sep)) +    { +        // If neither path nor name brings a separator to the junction, then +        // we need one. +        return SepOff(true, 0); +    } +    if (path_ends_sep && name_starts_sep) +    { +        // But if BOTH path and name bring a separator, we need not add one. +        // Moreover, we should actually skip the leading separator of 'name'. +        return SepOff(false, (unsigned short)seplen); +    } +    // Here we know that either path_ends_sep or name_starts_sep is true -- +    // but not both. So don't add a separator, and don't skip any characters: +    // simple concatenation will do the trick. +    return SepOff(false, 0);  }  void dir_exists_or_crash(const std::string &dir_name)  {  #if LL_WINDOWS -	// *FIX: lame - it doesn't do the same thing on windows. not so -	// important since we don't deploy simulator to windows boxes. -	LLFile::mkdir(dir_name, 0700); +    // *FIX: lame - it doesn't do the same thing on windows. not so +    // important since we don't deploy simulator to windows boxes. +    LLFile::mkdir(dir_name, 0700);  #else -	struct stat dir_stat; -	if(0 != LLFile::stat(dir_name, &dir_stat)) -	{ -		S32 stat_rv = errno; -		if(ENOENT == stat_rv) -		{ -		   if(0 != LLFile::mkdir(dir_name, 0700))		// octal -		   { -			   LL_ERRS() << "Unable to create directory: " << dir_name << LL_ENDL; -		   } -		} -		else -		{ -			LL_ERRS() << "Unable to stat: " << dir_name << " errno = " << stat_rv -				   << LL_ENDL; -		} -	} -	else -	{ -		// data_dir exists, make sure it's a directory. -		if(!S_ISDIR(dir_stat.st_mode)) -		{ -			LL_ERRS() << "Data directory collision: " << dir_name << LL_ENDL; -		} -	} +    struct stat dir_stat; +    if(0 != LLFile::stat(dir_name, &dir_stat)) +    { +        S32 stat_rv = errno; +        if(ENOENT == stat_rv) +        { +           if(0 != LLFile::mkdir(dir_name, 0700))       // octal +           { +               LL_ERRS() << "Unable to create directory: " << dir_name << LL_ENDL; +           } +        } +        else +        { +            LL_ERRS() << "Unable to stat: " << dir_name << " errno = " << stat_rv +                   << LL_ENDL; +        } +    } +    else +    { +        // data_dir exists, make sure it's a directory. +        if(!S_ISDIR(dir_stat.st_mode)) +        { +            LL_ERRS() << "Data directory collision: " << dir_name << LL_ENDL; +        } +    }  #endif  } diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h index d43921c292..be82f55e46 100644 --- a/indra/llfilesystem/lldir.h +++ b/indra/llfilesystem/lldir.h @@ -1,25 +1,25 @@ -/**   +/**   * @file lldir.h   * @brief Definition of directory utilities class   *   * $LicenseInfo:firstyear=2000&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -30,247 +30,245 @@  // these numbers are read from settings_files.xml, so we need to be explicit  typedef enum ELLPath  { -	LL_PATH_NONE = 0, -	LL_PATH_USER_SETTINGS = 1, -	LL_PATH_APP_SETTINGS = 2,	 -	LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet -	LL_PATH_CACHE = 4,	 -	LL_PATH_CHARACTER = 5,	 -	LL_PATH_HELP = 6,		 -	LL_PATH_LOGS = 7, -	LL_PATH_TEMP = 8, -	LL_PATH_SKINS = 9, -	LL_PATH_TOP_SKIN = 10, -	LL_PATH_CHAT_LOGS = 11, -	LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12, -	LL_PATH_USER_SKIN = 14, -	LL_PATH_LOCAL_ASSETS = 15, -	LL_PATH_EXECUTABLE = 16, -	LL_PATH_DEFAULT_SKIN = 17, -	LL_PATH_FONTS = 18, +    LL_PATH_NONE = 0, +    LL_PATH_USER_SETTINGS = 1, +    LL_PATH_APP_SETTINGS = 2, +    LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet +    LL_PATH_CACHE = 4, +    LL_PATH_CHARACTER = 5, +    LL_PATH_HELP = 6, +    LL_PATH_LOGS = 7, +    LL_PATH_TEMP = 8, +    LL_PATH_SKINS = 9, +    LL_PATH_TOP_SKIN = 10, +    LL_PATH_CHAT_LOGS = 11, +    LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12, +    LL_PATH_USER_SKIN = 14, +    LL_PATH_LOCAL_ASSETS = 15, +    LL_PATH_EXECUTABLE = 16, +    LL_PATH_DEFAULT_SKIN = 17, +    LL_PATH_FONTS = 18,      LL_PATH_DUMP = 19, -	LL_PATH_LAST +    LL_PATH_LAST  } ELLPath;  /// Directory operations  class LLDir  {   public: -	LLDir(); -	virtual ~LLDir(); +    LLDir(); +    virtual ~LLDir(); -	// app_name - Usually SecondLife, used for creating settings directories -	// in OS-specific location, such as C:\Documents and Settings -	// app_read_only_data_dir - Usually the source code directory, used -	// for test applications to read newview data files. -	virtual void initAppDirs(const std::string &app_name,  -		const std::string& app_read_only_data_dir = "") = 0; +    // app_name - Usually SecondLife, used for creating settings directories +    // in OS-specific location, such as C:\Documents and Settings +    // app_read_only_data_dir - Usually the source code directory, used +    // for test applications to read newview data files. +    virtual void initAppDirs(const std::string &app_name, +        const std::string& app_read_only_data_dir = "") = 0; -	virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask); +    virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);      U32 deleteDirAndContents(const std::string& dir_name);      std::vector<std::string> getFilesInDir(const std::string &dirname);  // pure virtual functions -	virtual std::string getCurPath() = 0; -	virtual bool fileExists(const std::string &filename) const = 0; -	virtual bool skinExists(const std::string& subdir, const std::string &skin) const; -	virtual std::string getFileContents(const std::string& filename) const; +    virtual std::string getCurPath() = 0; +    virtual bool fileExists(const std::string &filename) const = 0; -	const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const;  -	const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const; +    const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const; +    const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const; -	virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell -	virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so') +    virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell +    virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so') -	const std::string &getExecutablePathAndName() const;	// Full pathname of the executable -	const std::string &getAppName() const;			// install directory under progams/ ie "SecondLife" -	const std::string &getExecutableDir() const;	// Directory where the executable is located -	const std::string &getExecutableFilename() const;// Filename of .exe -	const std::string &getWorkingDir() const; // Current working directory -	const std::string &getAppRODataDir() const;	// Location of read-only data files -	const std::string &getOSUserDir() const;		// Location of the os-specific user dir -	const std::string &getOSUserAppDir() const;	// Location of the os-specific user app dir -	const std::string &getLindenUserDir() const;	// Location of the Linden user dir. -	const std::string &getChatLogsDir() const;	// Location of the chat logs dir. -	const std::string &getDumpDir() const;	// Location of the per-run dump dir. -	bool              dumpDirExists() const; -	const std::string &getPerAccountChatLogsDir() const;	// Location of the per account chat logs dir. -	const std::string &getTempDir() const;			// Common temporary directory -	const std::string  getCacheDir(bool get_default = false) const;	// Location of the cache. -	const std::string &getOSCacheDir() const;		// location of OS-specific cache folder (may be empty string) -	const std::string &getCAFile() const;			// File containing TLS certificate authorities -	const std::string &getDirDelimiter() const;	// directory separator for platform (ie. '\' or '/' or ':') -	const std::string &getDefaultSkinDir() const;	// folder for default skin. e.g. c:\program files\second life\skins\default -	const std::string &getSkinDir() const;		// User-specified skin folder. -	const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin -	const std::string &getUserSkinDir() const;		// User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin -	const std::string getSkinBaseDir() const;		// folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins -	const std::string &getLLPluginDir() const;		// Directory containing plugins and plugin shell -	const std::string &getUserName() const; +    const std::string &getExecutablePathAndName() const;    // Full pathname of the executable +    const std::string &getAppName() const;          // install directory under progams/ ie "SecondLife" +    const std::string &getExecutableDir() const;    // Directory where the executable is located +    const std::string &getExecutableFilename() const;// Filename of .exe +    const std::string &getWorkingDir() const; // Current working directory +    const std::string &getAppRODataDir() const; // Location of read-only data files +    const std::string &getOSUserDir() const;        // Location of the os-specific user dir +    const std::string &getOSUserAppDir() const; // Location of the os-specific user app dir +    const std::string &getLindenUserDir() const;    // Location of the Linden user dir. +    const std::string &getChatLogsDir() const;  // Location of the chat logs dir. +    const std::string &getDumpDir() const;  // Location of the per-run dump dir. +    bool              dumpDirExists() const; +    const std::string &getPerAccountChatLogsDir() const;    // Location of the per account chat logs dir. +    const std::string &getTempDir() const;          // Common temporary directory +    const std::string  getCacheDir(bool get_default = false) const; // Location of the cache. +    const std::string &getOSCacheDir() const;       // location of OS-specific cache folder (may be empty string) +    const std::string &getCAFile() const;           // File containing TLS certificate authorities +    const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':') +    const std::string &getDefaultSkinDir() const;   // folder for default skin. e.g. c:\program files\second life\skins\default +    const std::string &getSkinDir() const;      // User-specified skin folder. +    const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin +    const std::string &getUserSkinDir() const;      // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin +    const std::string getSkinBaseDir() const;       // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins +    const std::string &getLLPluginDir() const;      // Directory containing plugins and plugin shell +    const std::string &getUserName() const; -	// Expanded filename -	std::string getExpandedFilename(ELLPath location, const std::string &filename) const; -	std::string getExpandedFilename(ELLPath location, const std::string &subdir, const std::string &filename) const; -	std::string getExpandedFilename(ELLPath location, const std::string &subdir1, const std::string &subdir2, const std::string &filename) const; +    // Expanded filename +    std::string getExpandedFilename(ELLPath location, const std::string &filename) const; +    std::string getExpandedFilename(ELLPath location, const std::string &subdir, const std::string &filename) const; +    std::string getExpandedFilename(ELLPath location, const std::string &subdir1, const std::string &subdir2, const std::string &filename) const; -	// Base and Directory name extraction -	std::string getBaseFileName(const std::string& filepath, bool strip_exten = false) const; -	std::string getDirName(const std::string& filepath) const; -	std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav" +    // Base and Directory name extraction +    std::string getBaseFileName(const std::string& filepath, bool strip_exten = false) const; +    std::string getDirName(const std::string& filepath) const; +    std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav" -	// these methods search the various skin paths for the specified file in the following order: -	// getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir() -	/// param value for findSkinnedFilenames(), explained below -	enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS }; -	/** -	 * Given a filename within skin, return an ordered sequence of paths to -	 * search. Nonexistent files will be filtered out -- which means that the -	 * vector might be empty. -	 * -	 * @param subdir Identify top-level skin subdirectory by passing one of -	 * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file -	 * lives under "textures" subtree), LLDir::SKINBASE (file lives at top -	 * level of skin subdirectory). -	 * @param filename Desired filename within subdir within skin, e.g. -	 * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language. -	 * @param constraint Callers perform two different kinds of processing. -	 * When fetching a XUI file, for instance, the existence of @a filename in -	 * the specified skin completely supercedes any @a filename in the default -	 * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The -	 * returned vector will contain only -	 * ".../<i>current_skin</i>/xui/en/<i>filename</i>", -	 * ".../<i>current_skin</i>/xui/<i>current_language</i>/<i>filename</i>". -	 * But for (e.g.) "strings.xml", we want a given skin to be able to -	 * override only specific entries from the default skin. Any string not -	 * defined in the specified skin will be sought in the default skin. For -	 * that case, pass @a constraint=ALL_SKINS. The returned vector will -	 * contain at least ".../default/xui/en/strings.xml", -	 * ".../default/xui/<i>current_language</i>/strings.xml", -	 * ".../<i>current_skin</i>/xui/en/strings.xml", -	 * ".../<i>current_skin</i>/xui/<i>current_language</i>/strings.xml". -	 */ -	std::vector<std::string> findSkinnedFilenames(const std::string& subdir, -												  const std::string& filename, -												  ESkinConstraint constraint=CURRENT_SKIN) const; -	/// Values for findSkinnedFilenames(subdir) parameter -	static const char *XUI, *HTML, *TEXTURES, *SKINBASE; -	/** -	 * Return the base-language pathname from findSkinnedFilenames(), or -	 * the empty string if no such file exists. Parameters are identical to -	 * findSkinnedFilenames(). This is shorthand for capturing the vector -	 * returned by findSkinnedFilenames(), checking for empty() and then -	 * returning front(). -	 */ -	std::string findSkinnedFilenameBaseLang(const std::string &subdir, -											const std::string &filename, -											ESkinConstraint constraint=CURRENT_SKIN) const; -	/** -	 * Return the "most localized" pathname from findSkinnedFilenames(), or -	 * the empty string if no such file exists. Parameters are identical to -	 * findSkinnedFilenames(). This is shorthand for capturing the vector -	 * returned by findSkinnedFilenames(), checking for empty() and then -	 * returning back(). -	 */ -	std::string findSkinnedFilename(const std::string &subdir, -									const std::string &filename, -									ESkinConstraint constraint=CURRENT_SKIN) const; +    // these methods search the various skin paths for the specified file in the following order: +    // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir() +    /// param value for findSkinnedFilenames(), explained below +    enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS }; +    /** +     * Given a filename within skin, return an ordered sequence of paths to +     * search. Nonexistent files will be filtered out -- which means that the +     * vector might be empty. +     * +     * @param subdir Identify top-level skin subdirectory by passing one of +     * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file +     * lives under "textures" subtree), LLDir::SKINBASE (file lives at top +     * level of skin subdirectory). +     * @param filename Desired filename within subdir within skin, e.g. +     * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language. +     * @param constraint Callers perform two different kinds of processing. +     * When fetching a XUI file, for instance, the existence of @a filename in +     * the specified skin completely supercedes any @a filename in the default +     * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The +     * returned vector will contain only +     * ".../<i>current_skin</i>/xui/en/<i>filename</i>", +     * ".../<i>current_skin</i>/xui/<i>current_language</i>/<i>filename</i>". +     * But for (e.g.) "strings.xml", we want a given skin to be able to +     * override only specific entries from the default skin. Any string not +     * defined in the specified skin will be sought in the default skin. For +     * that case, pass @a constraint=ALL_SKINS. The returned vector will +     * contain at least ".../default/xui/en/strings.xml", +     * ".../default/xui/<i>current_language</i>/strings.xml", +     * ".../<i>current_skin</i>/xui/en/strings.xml", +     * ".../<i>current_skin</i>/xui/<i>current_language</i>/strings.xml". +     */ +    std::vector<std::string> findSkinnedFilenames(const std::string& subdir, +                                                  const std::string& filename, +                                                  ESkinConstraint constraint=CURRENT_SKIN) const; +    /// Values for findSkinnedFilenames(subdir) parameter +    static const char *XUI, *TEXTURES, *SKINBASE; +    /** +     * Return the base-language pathname from findSkinnedFilenames(), or +     * the empty string if no such file exists. Parameters are identical to +     * findSkinnedFilenames(). This is shorthand for capturing the vector +     * returned by findSkinnedFilenames(), checking for empty() and then +     * returning front(). +     */ +    std::string findSkinnedFilenameBaseLang(const std::string &subdir, +                                            const std::string &filename, +                                            ESkinConstraint constraint=CURRENT_SKIN) const; +    /** +     * Return the "most localized" pathname from findSkinnedFilenames(), or +     * the empty string if no such file exists. Parameters are identical to +     * findSkinnedFilenames(). This is shorthand for capturing the vector +     * returned by findSkinnedFilenames(), checking for empty() and then +     * returning back(). +     */ +    std::string findSkinnedFilename(const std::string &subdir, +                                    const std::string &filename, +                                    ESkinConstraint constraint=CURRENT_SKIN) const; -	// random filename in common temporary directory -	std::string getTempFilename() const; +    // random filename in common temporary directory +    std::string getTempFilename() const;      static std::string getDumpLogsDirPath(const std::string &file_name = ""); -	// For producing safe download file names from potentially unsafe ones -	static std::string getScrubbedFileName(const std::string uncleanFileName); -	static std::string getForbiddenFileChars(); +    // For producing safe download file names from potentially unsafe ones +    static std::string getScrubbedFileName(const std::string uncleanFileName); +    static std::string getForbiddenFileChars();      void setDumpDir( const std::string& path ); -	virtual void setChatLogsDir(const std::string &path);		// Set the chat logs dir to this user's dir -	virtual void setPerAccountChatLogsDir(const std::string &username);		// Set the per user chat log directory. -	virtual void setLindenUserDir(const std::string &username);		// Set the linden user dir to this user's dir -	virtual void setSkinFolder(const std::string &skin_folder, const std::string& language); -	virtual std::string getSkinFolder() const; -	virtual std::string getLanguage() const; -	virtual bool setCacheDir(const std::string &path); -	virtual void updatePerAccountChatLogsDir(); +    virtual void setChatLogsDir(const std::string &path);       // Set the chat logs dir to this user's dir +    virtual void setPerAccountChatLogsDir(const std::string &username);     // Set the per user chat log directory. +    virtual void setLindenUserDir(const std::string &username);     // Set the linden user dir to this user's dir +    virtual void setSkinFolder(const std::string &skin_folder, const std::string& language); +    virtual std::string getSkinFolder() const; +    virtual std::string getLanguage() const; +    virtual bool setCacheDir(const std::string &path); +    virtual void updatePerAccountChatLogsDir(); -	virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG); +    virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG); -	// Utility routine -	std::string buildSLOSCacheDir() const; +    // Utility routine +    std::string buildSLOSCacheDir() const; -	/// Append specified @a name to @a destpath, separated by getDirDelimiter() -	/// if both are non-empty. -	void append(std::string& destpath, const std::string& name) const; -	/// Variadic form: append @a name0 and @a name1 and arbitrary other @a -	/// names to @a destpath, separated by getDirDelimiter() as needed. -	template <typename... NAMES> -	void append(std::string& destpath, const std::string& name0, const std::string& name1, -				const NAMES& ... names) const -	{ -		// In a typical recursion case, we'd accept (destpath, name0, names). -		// We accept (destpath, name0, name1, names) because it's important to -		// delegate the two-argument case to the non-template implementation. -		append(destpath, name0); -		append(destpath, name1, names...); -	} +    /// Append specified @a name to @a destpath, separated by getDirDelimiter() +    /// if both are non-empty. +    void append(std::string& destpath, const std::string& name) const; +    /// Variadic form: append @a name0 and @a name1 and arbitrary other @a +    /// names to @a destpath, separated by getDirDelimiter() as needed. +    template <typename... NAMES> +    void append(std::string& destpath, const std::string& name0, const std::string& name1, +                const NAMES& ... names) const +    { +        // In a typical recursion case, we'd accept (destpath, name0, names). +        // We accept (destpath, name0, name1, names) because it's important to +        // delegate the two-argument case to the non-template implementation. +        append(destpath, name0); +        append(destpath, name1, names...); +    } -	/// Append specified @a names to @a path, separated by getDirDelimiter() -	/// as needed. Return result, leaving @a path unmodified. -	template <typename... NAMES> -	std::string add(const std::string& path, const NAMES& ... names) const -	{ -		std::string destpath(path); -		append(destpath, names...); -		return destpath; -	} +    /// Append specified @a names to @a path, separated by getDirDelimiter() +    /// as needed. Return result, leaving @a path unmodified. +    template <typename... NAMES> +    std::string add(const std::string& path, const NAMES& ... names) const +    { +        std::string destpath(path); +        append(destpath, names...); +        return destpath; +    }  protected: -	// Does an add() or append() call need a directory delimiter? -	typedef std::pair<bool, unsigned short> SepOff; -	SepOff needSep(const std::string& path, const std::string& name) const; -	// build mSearchSkinDirs without adding duplicates -	void addSearchSkinDir(const std::string& skindir); +    // Does an add() or append() call need a directory delimiter? +    typedef std::pair<bool, unsigned short> SepOff; +    SepOff needSep(const std::string& path, const std::string& name) const; +    // build mSearchSkinDirs without adding duplicates +    void addSearchSkinDir(const std::string& skindir); -	// Internal to findSkinnedFilenames() -	template <typename FUNCTION> -	void walkSearchSkinDirs(const std::string& subdir, -							const std::vector<std::string>& subsubdirs, -							const std::string& filename, -							const FUNCTION& function) const; +    // Internal to findSkinnedFilenames() +    template <typename FUNCTION> +    void walkSearchSkinDirs(const std::string& subdir, +                            const std::vector<std::string>& subsubdirs, +                            const std::string& filename, +                            const FUNCTION& function) const; -	std::string mAppName;               // install directory under progams/ ie "SecondLife"    -	std::string mExecutablePathAndName; // full path + Filename of .exe -	std::string mExecutableFilename;    // Filename of .exe -	std::string mExecutableDir;	 	 // Location of executable -	std::string mWorkingDir;	 	 // Current working directory -	std::string mAppRODataDir;			 // Location for static app data -	std::string mOSUserDir;			 // OS Specific user directory -	std::string mOSUserAppDir;			 // OS Specific user app directory -	std::string mLindenUserDir;		 // Location for Linden user-specific data -	std::string mPerAccountChatLogsDir;		 // Location for chat logs. -	std::string mChatLogsDir;		 // Location for chat logs. -	std::string mCAFile;				 // Location of the TLS certificate authority PEM file. -	std::string mTempDir; -	std::string mCacheDir;			// cache directory as set by user preference -	std::string mDefaultCacheDir;	// default cache diretory -	std::string mOSCacheDir;		// operating system cache dir -	std::string mDirDelimiter; -	std::string mSkinName;           // caller-specified skin name -	std::string mSkinBaseDir;			// Base for skins paths. -	std::string mDefaultSkinDir;			// Location for default skin info. -	std::string mSkinDir;			// Location for current skin info. -	std::string mUserDefaultSkinDir;		// Location for default skin info. -	std::string mUserSkinDir;			// Location for user-modified skin info. -	// Skin directories to search, most general to most specific. This order -	// works well for composing fine-grained files, in which an individual item -	// in a specific file overrides the corresponding item in more general -	// files. Of course, for a file-level search, iterate backwards. -	std::vector<std::string> mSearchSkinDirs; -	std::string mLanguage;              // Current viewer language -	std::string mLLPluginDir;			// Location for plugins and plugin shell +    std::string mAppName;               // install directory under progams/ ie "SecondLife" +    std::string mExecutablePathAndName; // full path + Filename of .exe +    std::string mExecutableFilename;    // Filename of .exe +    std::string mExecutableDir;      // Location of executable +    std::string mWorkingDir;         // Current working directory +    std::string mAppRODataDir;           // Location for static app data +    std::string mOSUserDir;          // OS Specific user directory +    std::string mOSUserAppDir;           // OS Specific user app directory +    std::string mLindenUserDir;      // Location for Linden user-specific data +    std::string mPerAccountChatLogsDir;      // Location for chat logs. +    std::string mChatLogsDir;        // Location for chat logs. +    std::string mCAFile;                 // Location of the TLS certificate authority PEM file. +    std::string mTempDir; +    std::string mCacheDir;          // cache directory as set by user preference +    std::string mDefaultCacheDir;   // default cache diretory +    std::string mOSCacheDir;        // operating system cache dir +    std::string mDirDelimiter; +    std::string mSkinName;           // caller-specified skin name +    std::string mSkinBaseDir;           // Base for skins paths. +    std::string mDefaultSkinDir;            // Location for default skin info. +    std::string mSkinDir;           // Location for current skin info. +    std::string mUserDefaultSkinDir;        // Location for default skin info. +    std::string mUserSkinDir;           // Location for user-modified skin info. +    // Skin directories to search, most general to most specific. This order +    // works well for composing fine-grained files, in which an individual item +    // in a specific file overrides the corresponding item in more general +    // files. Of course, for a file-level search, iterate backwards. +    std::vector<std::string> mSearchSkinDirs; +    std::string mLanguage;              // Current viewer language +    std::string mLLPluginDir;           // Location for plugins and plugin shell      static std::string sDumpDir;            // Per-run crash report subdir of log directory. -	std::string mUserName;				// Current user name +    std::string mUserName;              // Current user name  };  void dir_exists_or_crash(const std::string &dir_name); diff --git a/indra/llfilesystem/lldir_linux.cpp b/indra/llfilesystem/lldir_linux.cpp index 44e24a1625..b13b42c954 100644 --- a/indra/llfilesystem/lldir_linux.cpp +++ b/indra/llfilesystem/lldir_linux.cpp @@ -1,25 +1,25 @@ -/**  +/**   * @file lldir_linux.cpp   * @brief Implementation of directory utilities for linux   *   * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -39,104 +39,104 @@  static std::string getCurrentUserHome(char* fallback)  { -	const uid_t uid = getuid(); -	struct passwd *pw; - -	pw = getpwuid(uid); -	if ((pw != NULL) && (pw->pw_dir != NULL)) -	{ -		return pw->pw_dir; -	} - -	LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL; -	auto home_env = LLStringUtil::getoptenv("HOME"); -	if (home_env) -	{ -		return *home_env; -	} -	else -	{ -		LL_WARNS() << "Couldn't detect home directory!  Falling back to " << fallback << LL_ENDL; -		return fallback; -	} +    const uid_t uid = getuid(); +    struct passwd *pw; + +    pw = getpwuid(uid); +    if ((pw != NULL) && (pw->pw_dir != NULL)) +    { +        return pw->pw_dir; +    } + +    LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL; +    auto home_env = LLStringUtil::getoptenv("HOME"); +    if (home_env) +    { +        return *home_env; +    } +    else +    { +        LL_WARNS() << "Couldn't detect home directory!  Falling back to " << fallback << LL_ENDL; +        return fallback; +    }  }  LLDir_Linux::LLDir_Linux()  { -	mDirDelimiter = "/"; -	mCurrentDirIndex = -1; -	mCurrentDirCount = -1; -	mDirp = NULL; - -	char tmp_str[LL_MAX_PATH];	/* Flawfinder: ignore */  -	if (getcwd(tmp_str, LL_MAX_PATH) == NULL) -	{ -		strcpy(tmp_str, "/tmp"); -		LL_WARNS() << "Could not get current directory; changing to " -				<< tmp_str << LL_ENDL; -		if (chdir(tmp_str) == -1) -		{ -			LL_ERRS() << "Could not change directory to " << tmp_str << LL_ENDL; -		} -	} - -	mExecutableFilename = ""; -	mExecutablePathAndName = ""; -	mExecutableDir = tmp_str; -	mWorkingDir = tmp_str; +    mDirDelimiter = "/"; +    mCurrentDirIndex = -1; +    mCurrentDirCount = -1; +    mDirp = NULL; + +    char tmp_str[LL_MAX_PATH];  /* Flawfinder: ignore */ +    if (getcwd(tmp_str, LL_MAX_PATH) == NULL) +    { +        strcpy(tmp_str, "/tmp"); +        LL_WARNS() << "Could not get current directory; changing to " +                << tmp_str << LL_ENDL; +        if (chdir(tmp_str) == -1) +        { +            LL_ERRS() << "Could not change directory to " << tmp_str << LL_ENDL; +        } +    } + +    mExecutableFilename = ""; +    mExecutablePathAndName = ""; +    mExecutableDir = tmp_str; +    mWorkingDir = tmp_str;  #ifdef APP_RO_DATA_DIR -	mAppRODataDir = APP_RO_DATA_DIR; +    mAppRODataDir = APP_RO_DATA_DIR;  #else -	mAppRODataDir = tmp_str; +    mAppRODataDir = tmp_str;  #endif      std::string::size_type build_dir_pos = mExecutableDir.rfind("/build-linux-");      if (build_dir_pos != std::string::npos)      { -		// ...we're in a dev checkout -		mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "/indra/newview/skins"; -		LL_INFOS() << "Running in dev checkout with mSkinBaseDir " -		 << mSkinBaseDir << LL_ENDL; +        // ...we're in a dev checkout +        mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "/indra/newview/skins"; +        LL_INFOS() << "Running in dev checkout with mSkinBaseDir " +         << mSkinBaseDir << LL_ENDL;      }      else      { -		// ...normal installation running -		mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; -    }	 - -	mOSUserDir = getCurrentUserHome(tmp_str); -	mOSUserAppDir = ""; -	mLindenUserDir = ""; - -	char path [32];	/* Flawfinder: ignore */  - -	// *NOTE: /proc/%d/exe doesn't work on FreeBSD. But that's ok, -	// because this is the linux implementation. - -	snprintf (path, sizeof(path), "/proc/%d/exe", (int) getpid ());  -	int rc = readlink (path, tmp_str, sizeof (tmp_str)-1);	/* Flawfinder: ignore */  -	if ( (rc != -1) && (rc <= ((int) sizeof (tmp_str)-1)) ) -	{ -		tmp_str[rc] = '\0'; //readlink() doesn't 0-terminate the buffer -		mExecutablePathAndName = tmp_str; -		char *path_end; -		if ((path_end = strrchr(tmp_str,'/'))) -		{ -			*path_end = '\0'; -			mExecutableDir = tmp_str; -			mWorkingDir = tmp_str; -			mExecutableFilename = path_end+1; -		} -		else -		{ -			mExecutableFilename = tmp_str; -		} -	} - -	mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin"; - -	// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. -	mTempDir = "/tmp"; +        // ...normal installation running +        mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; +    } + +    mOSUserDir = getCurrentUserHome(tmp_str); +    mOSUserAppDir = ""; +    mLindenUserDir = ""; + +    char path [32]; /* Flawfinder: ignore */ + +    // *NOTE: /proc/%d/exe doesn't work on FreeBSD. But that's ok, +    // because this is the linux implementation. + +    snprintf (path, sizeof(path), "/proc/%d/exe", (int) getpid ()); +    int rc = readlink (path, tmp_str, sizeof (tmp_str)-1);  /* Flawfinder: ignore */ +    if ( (rc != -1) && (rc <= ((int) sizeof (tmp_str)-1)) ) +    { +        tmp_str[rc] = '\0'; //readlink() doesn't 0-terminate the buffer +        mExecutablePathAndName = tmp_str; +        char *path_end; +        if ((path_end = strrchr(tmp_str,'/'))) +        { +            *path_end = '\0'; +            mExecutableDir = tmp_str; +            mWorkingDir = tmp_str; +            mExecutableFilename = path_end+1; +        } +        else +        { +            mExecutableFilename = tmp_str; +        } +    } + +    mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin"; + +    // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. +    mTempDir = "/tmp";  }  LLDir_Linux::~LLDir_Linux() @@ -147,123 +147,123 @@ LLDir_Linux::~LLDir_Linux()  void LLDir_Linux::initAppDirs(const std::string &app_name, -							  const std::string& app_read_only_data_dir) +                              const std::string& app_read_only_data_dir)  { -	// Allow override so test apps can read newview directory -	if (!app_read_only_data_dir.empty()) -	{ -		mAppRODataDir = app_read_only_data_dir; -		mSkinBaseDir = add(mAppRODataDir, "skins"); -	} -	mAppName = app_name; - -	std::string upper_app_name(app_name); -	LLStringUtil::toUpper(upper_app_name); - -	auto app_home_env(LLStringUtil::getoptenv(upper_app_name + "_USER_DIR")); -	if (app_home_env) -	{ -		// user has specified own userappdir i.e. $SECONDLIFE_USER_DIR -		mOSUserAppDir = *app_home_env; -	} -	else -	{ -		// traditionally on unixoids, MyApp gets ~/.myapp dir for data -		mOSUserAppDir = mOSUserDir; -		mOSUserAppDir += "/"; -		mOSUserAppDir += "."; -		std::string lower_app_name(app_name); -		LLStringUtil::toLower(lower_app_name); -		mOSUserAppDir += lower_app_name; -	} - -	// create any directories we expect to write to. - -	int res = LLFile::mkdir(mOSUserAppDir); -	if (res == -1) -	{ -		LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL; -		LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL; -		mOSUserAppDir = mOSUserDir; -	} - -	res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"")); -	if (res == -1) -	{ -		LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL; -	} -	 -	res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"")); -	if (res == -1) -	{ -		LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL; -	} - -	res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"")); -	if (res == -1) -	{ -		LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; -	} - -	mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "ca-bundle.crt"); +    // Allow override so test apps can read newview directory +    if (!app_read_only_data_dir.empty()) +    { +        mAppRODataDir = app_read_only_data_dir; +        mSkinBaseDir = add(mAppRODataDir, "skins"); +    } +    mAppName = app_name; + +    std::string upper_app_name(app_name); +    LLStringUtil::toUpper(upper_app_name); + +    auto app_home_env(LLStringUtil::getoptenv(upper_app_name + "_USER_DIR")); +    if (app_home_env) +    { +        // user has specified own userappdir i.e. $SECONDLIFE_USER_DIR +        mOSUserAppDir = *app_home_env; +    } +    else +    { +        // traditionally on unixoids, MyApp gets ~/.myapp dir for data +        mOSUserAppDir = mOSUserDir; +        mOSUserAppDir += "/"; +        mOSUserAppDir += "."; +        std::string lower_app_name(app_name); +        LLStringUtil::toLower(lower_app_name); +        mOSUserAppDir += lower_app_name; +    } + +    // create any directories we expect to write to. + +    int res = LLFile::mkdir(mOSUserAppDir); +    if (res == -1) +    { +        LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL; +        LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL; +        mOSUserAppDir = mOSUserDir; +    } + +    res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"")); +    if (res == -1) +    { +        LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL; +    } + +    res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"")); +    if (res == -1) +    { +        LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL; +    } + +    res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"")); +    if (res == -1) +    { +        LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; +    } + +    mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "ca-bundle.crt");  }  U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string &mask)  { -	U32 file_count = 0; -	glob_t g; +    U32 file_count = 0; +    glob_t g; -	std::string tmp_str; -	tmp_str = dirname; -	tmp_str += mask; -	 -	if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) -	{ -		file_count = g.gl_pathc; +    std::string tmp_str; +    tmp_str = dirname; +    tmp_str += mask; -		globfree(&g); -	} +    if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) +    { +        file_count = g.gl_pathc; + +        globfree(&g); +    } -	return (file_count); +    return (file_count);  }  std::string LLDir_Linux::getCurPath()  { -	char tmp_str[LL_MAX_PATH];	/* Flawfinder: ignore */  -	if (getcwd(tmp_str, LL_MAX_PATH) == NULL) -	{ -		LL_WARNS() << "Could not get current directory" << LL_ENDL; -		tmp_str[0] = '\0'; -	} -	return tmp_str; +    char tmp_str[LL_MAX_PATH];  /* Flawfinder: ignore */ +    if (getcwd(tmp_str, LL_MAX_PATH) == NULL) +    { +        LL_WARNS() << "Could not get current directory" << LL_ENDL; +        tmp_str[0] = '\0'; +    } +    return tmp_str;  }  bool LLDir_Linux::fileExists(const std::string &filename) const  { -	struct stat stat_data; -	// Check the age of the file -	// Now, we see if the files we've gathered are recent... -	int res = stat(filename.c_str(), &stat_data); -	if (!res) -	{ -		return true; -	} -	else -	{ -		return false; -	} +    struct stat stat_data; +    // Check the age of the file +    // Now, we see if the files we've gathered are recent... +    int res = stat(filename.c_str(), &stat_data); +    if (!res) +    { +        return true; +    } +    else +    { +        return false; +    }  }  /*virtual*/ std::string LLDir_Linux::getLLPluginLauncher()  { -	return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + -		"SLPlugin"; +    return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + +        "SLPlugin";  }  /*virtual*/ std::string LLDir_Linux::getLLPluginFilename(std::string base_name)  { -	return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + -		"lib" + base_name + ".so"; +    return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + +        "lib" + base_name + ".so";  } diff --git a/indra/llfilesystem/lldir_linux.h b/indra/llfilesystem/lldir_linux.h index e83a020ba4..bd031bd7bb 100644 --- a/indra/llfilesystem/lldir_linux.h +++ b/indra/llfilesystem/lldir_linux.h @@ -1,25 +1,25 @@ -/**  +/**   * @file lldir_linux.h   * @brief Definition of directory utilities class for linux   *   * $LicenseInfo:firstyear=2000&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -39,24 +39,24 @@  class LLDir_Linux : public LLDir  {  public: -	LLDir_Linux(); -	virtual ~LLDir_Linux(); +    LLDir_Linux(); +    virtual ~LLDir_Linux(); -	/*virtual*/ void initAppDirs(const std::string &app_name, -		const std::string& app_read_only_data_dir); +    /*virtual*/ void initAppDirs(const std::string &app_name, +        const std::string& app_read_only_data_dir); -	virtual std::string getCurPath(); -	virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); -	/*virtual*/ bool fileExists(const std::string &filename) const; +    virtual std::string getCurPath(); +    virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); +    /*virtual*/ bool fileExists(const std::string &filename) const; -	/*virtual*/ std::string getLLPluginLauncher(); -	/*virtual*/ std::string getLLPluginFilename(std::string base_name); +    /*virtual*/ std::string getLLPluginLauncher(); +    /*virtual*/ std::string getLLPluginFilename(std::string base_name);  private: -	DIR *mDirp; -	int mCurrentDirIndex; -	int mCurrentDirCount; -	std::string mCurrentDir; +    DIR *mDirp; +    int mCurrentDirIndex; +    int mCurrentDirCount; +    std::string mCurrentDir;  };  #endif // LL_LLDIR_LINUX_H diff --git a/indra/llfilesystem/lldir_mac.cpp b/indra/llfilesystem/lldir_mac.cpp index 0d9695e161..b9be75c528 100644 --- a/indra/llfilesystem/lldir_mac.cpp +++ b/indra/llfilesystem/lldir_mac.cpp @@ -1,28 +1,28 @@ -/**  +/**   * @file lldir_mac.cpp   * @brief Implementation of directory utilities for macOS   *   * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$ - */  + */  #if LL_DARWIN @@ -40,17 +40,17 @@  // -------------------------------------------------------------------------------- -static bool CreateDirectory(const std::string &parent,  +static bool CreateDirectory(const std::string &parent,                              const std::string &child,                              std::string *fullname)  { -     +      boost::filesystem::path p(parent);      p /= child; -     +      if (fullname)          *fullname = std::string(p.string()); -     +      if (! boost::filesystem::create_directory(p))      {          return (boost::filesystem::is_directory(p)); @@ -62,95 +62,95 @@ static bool CreateDirectory(const std::string &parent,  LLDir_Mac::LLDir_Mac()  { -	mDirDelimiter = "/"; +    mDirDelimiter = "/";      const std::string     secondLifeString = "SecondLife"; -     +      std::string executablepathstr = getSystemExecutableFolder();      //NOTE:  LLINFOS/LLERRS will not output to log here.  The streams are not initialized. -     -	if (!executablepathstr.empty()) -	{ -		// mExecutablePathAndName -		mExecutablePathAndName = executablepathstr; -         + +    if (!executablepathstr.empty()) +    { +        // mExecutablePathAndName +        mExecutablePathAndName = executablepathstr; +          boost::filesystem::path executablepath(executablepathstr); -         +  # ifndef BOOST_SYSTEM_NO_DEPRECATED  #endif          mExecutableFilename = executablepath.filename().string();          mExecutableDir = executablepath.parent_path().string(); -		 -		// mAppRODataDir + +        // mAppRODataDir          std::string resourcepath = getSystemResourceFolder();          mAppRODataDir = resourcepath; -		 -		// *NOTE: When running in a dev tree, use the copy of -		// skins in indra/newview/ rather than in the application bundle.  This -		// mirrors Windows dev environment behavior and allows direct checkin -		// of edited skins/xui files. JC -		 -		// MBW -- This keeps the mac application from finding other things. -		// If this is really for skins, it should JUST apply to skins. -         -		std::string::size_type build_dir_pos = mExecutableDir.rfind("/build-darwin-"); -		if (build_dir_pos != std::string::npos) -		{ -			// ...we're in a dev checkout -			mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) -				+ "/indra/newview/skins"; -			LL_INFOS() << "Running in dev checkout with mSkinBaseDir " -				<< mSkinBaseDir << LL_ENDL; -		} -		else -		{ -			// ...normal installation running -			mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; -		} -		 -		// mOSUserDir + +        // *NOTE: When running in a dev tree, use the copy of +        // skins in indra/newview/ rather than in the application bundle.  This +        // mirrors Windows dev environment behavior and allows direct checkin +        // of edited skins/xui files. JC + +        // MBW -- This keeps the mac application from finding other things. +        // If this is really for skins, it should JUST apply to skins. + +        std::string::size_type build_dir_pos = mExecutableDir.rfind("/build-darwin-"); +        if (build_dir_pos != std::string::npos) +        { +            // ...we're in a dev checkout +            mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) +                + "/indra/newview/skins"; +            LL_INFOS() << "Running in dev checkout with mSkinBaseDir " +                << mSkinBaseDir << LL_ENDL; +        } +        else +        { +            // ...normal installation running +            mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; +        } + +        // mOSUserDir          std::string appdir = getSystemApplicationSupportFolder();          std::string rootdir;          //Create root directory          if (CreateDirectory(appdir, secondLifeString, &rootdir))          { -             +              // Save the full path to the folder              mOSUserDir = rootdir; -             +              // Create our sub-dirs              CreateDirectory(rootdir, std::string("data"), NULL);              CreateDirectory(rootdir, std::string("logs"), NULL);              CreateDirectory(rootdir, std::string("user_settings"), NULL);              CreateDirectory(rootdir, std::string("browser_profile"), NULL);          } -     -		//mOSCacheDir + +        //mOSCacheDir          std::string cachedir =  getSystemCacheFolder();          if (!cachedir.empty()) -		{ +        {              mOSCacheDir = cachedir;              //TODO:  This changes from ~/Library/Cache/Secondlife to ~/Library/Cache/com.app.secondlife/Secondlife.  Last dir level could go away.              CreateDirectory(mOSCacheDir, secondLifeString, NULL); -		} -		 -		// mOSUserAppDir -		mOSUserAppDir = mOSUserDir; -		 -		// mTempDir +        } + +        // mOSUserAppDir +        mOSUserAppDir = mOSUserDir; + +        // mTempDir          //Aura 120920 boost::filesystem::temp_directory_path() not yet implemented on mac. :(          std::string tmpdir = getSystemTempFolder();          if (!tmpdir.empty())          {              CreateDirectory(tmpdir, secondLifeString, &mTempDir);          } -		 -		mWorkingDir = getCurPath(); -		mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin"; -	} +        mWorkingDir = getCurPath(); + +        mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin"; +    }  }  LLDir_Mac::~LLDir_Mac() @@ -161,20 +161,20 @@ LLDir_Mac::~LLDir_Mac()  void LLDir_Mac::initAppDirs(const std::string &app_name, -							const std::string& app_read_only_data_dir) +                            const std::string& app_read_only_data_dir)  { -	// Allow override so test apps can read newview directory -	if (!app_read_only_data_dir.empty()) -	{ -		mAppRODataDir = app_read_only_data_dir; -		mSkinBaseDir = add(mAppRODataDir, "skins"); -	} -	mCAFile = add(mAppRODataDir, "ca-bundle.crt"); +    // Allow override so test apps can read newview directory +    if (!app_read_only_data_dir.empty()) +    { +        mAppRODataDir = app_read_only_data_dir; +        mSkinBaseDir = add(mAppRODataDir, "skins"); +    } +    mCAFile = add(mAppRODataDir, "ca-bundle.crt");  }  std::string LLDir_Mac::getCurPath()  { -	return boost::filesystem::path( boost::filesystem::current_path() ).string(); +    return boost::filesystem::path( boost::filesystem::current_path() ).string();  } @@ -187,14 +187,14 @@ bool LLDir_Mac::fileExists(const std::string &filename) const  /*virtual*/ std::string LLDir_Mac::getLLPluginLauncher()  { -	return gDirUtilp->getAppRODataDir() + gDirUtilp->getDirDelimiter() + -		"SLPlugin.app/Contents/MacOS/SLPlugin"; +    return gDirUtilp->getAppRODataDir() + gDirUtilp->getDirDelimiter() + +        "SLPlugin.app/Contents/MacOS/SLPlugin";  }  /*virtual*/ std::string LLDir_Mac::getLLPluginFilename(std::string base_name)  { -	return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + -		base_name + ".dylib"; +    return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + +        base_name + ".dylib";  } diff --git a/indra/llfilesystem/lldir_mac.h b/indra/llfilesystem/lldir_mac.h index 0290fb773b..f812ee810b 100644 --- a/indra/llfilesystem/lldir_mac.h +++ b/indra/llfilesystem/lldir_mac.h @@ -1,28 +1,28 @@ -/**  +/**   * @file lldir_mac.h   * @brief Definition of directory utilities class for macOS   *   * $LicenseInfo:firstyear=2000&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$ - */  + */  #if !LL_DARWIN  #error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead. @@ -38,17 +38,17 @@  class LLDir_Mac : public LLDir  {  public: -	LLDir_Mac(); -	virtual ~LLDir_Mac(); +    LLDir_Mac(); +    virtual ~LLDir_Mac(); -	/*virtual*/ void initAppDirs(const std::string &app_name, -		const std::string& app_read_only_data_dir); +    /*virtual*/ void initAppDirs(const std::string &app_name, +        const std::string& app_read_only_data_dir); -	virtual std::string getCurPath(); -	virtual bool fileExists(const std::string &filename) const; +    virtual std::string getCurPath(); +    virtual bool fileExists(const std::string &filename) const; -	/*virtual*/ std::string getLLPluginLauncher(); -	/*virtual*/ std::string getLLPluginFilename(std::string base_name); +    /*virtual*/ std::string getLLPluginLauncher(); +    /*virtual*/ std::string getLLPluginFilename(std::string base_name);  };  #endif // LL_LLDIR_MAC_H diff --git a/indra/llfilesystem/lldir_win32.cpp b/indra/llfilesystem/lldir_win32.cpp index f65cc90dc3..0fca4004b6 100644 --- a/indra/llfilesystem/lldir_win32.cpp +++ b/indra/llfilesystem/lldir_win32.cpp @@ -1,25 +1,25 @@ -/**  +/**   * @file lldir_win32.cpp   * @brief Implementation of directory utilities for windows   *   * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -94,200 +94,200 @@ namespace  LLDir_Win32::LLDir_Win32()  { -	// set this first: used by append() and add() methods -	mDirDelimiter = "\\"; - -	WCHAR w_str[MAX_PATH]; -	// Application Data is where user settings go. We rely on $APPDATA being -	// correct. -	auto APPDATA = LLStringUtil::getoptenv("APPDATA"); -	if (APPDATA) -	{ -		mOSUserDir = *APPDATA; -	} -	PRELOG("APPDATA='" << mOSUserDir << "'"); -	// On Windows, we could have received a plain-ASCII pathname in which -	// non-ASCII characters have been munged to '?', or the pathname could -	// have been badly encoded and decoded such that we now have garbage -	// instead of a valid path. Check that mOSUserDir actually exists. -	if (mOSUserDir.empty() || ! fileExists(mOSUserDir)) -	{ -		PRELOG("APPDATA does not exist"); -		//HRESULT okay = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, w_str); -		wchar_t *pwstr = NULL; -		HRESULT okay = SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &pwstr); -		PRELOG("SHGetKnownFolderPath(FOLDERID_RoamingAppData) returned " << okay); -		if (SUCCEEDED(okay) && pwstr) -		{ -			// But of course, only update mOSUserDir if SHGetKnownFolderPath() works. -			mOSUserDir = ll_convert_wide_to_string(pwstr); -			// Not only that: update our environment so that child processes -			// will see a reasonable value as well. -			_wputenv_s(L"APPDATA", pwstr); -			// SHGetKnownFolderPath() contract requires us to free pwstr -			CoTaskMemFree(pwstr); -			PRELOG("mOSUserDir='" << mOSUserDir << "'"); -		} -	} - -	// We want cache files to go on the local disk, even if the -	// user is on a network with a "roaming profile". -	// -	// On Vista this is: -	//   C:\Users\James\AppData\Local -	// -	// We used to store the cache in AppData\Roaming, and the installer -	// cleans up that version on upgrade.  JC -	auto LOCALAPPDATA = LLStringUtil::getoptenv("LOCALAPPDATA"); -	if (LOCALAPPDATA) -	{ -		mOSCacheDir = *LOCALAPPDATA; -	} -	PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'"); -	// Windows really does not deal well with pathnames containing non-ASCII -	// characters. See above remarks about APPDATA. -	if (mOSCacheDir.empty() || ! fileExists(mOSCacheDir)) -	{ -		PRELOG("LOCALAPPDATA does not exist"); -		//HRESULT okay = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, w_str); -		wchar_t *pwstr = NULL; -		HRESULT okay = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pwstr); -		PRELOG("SHGetKnownFolderPath(FOLDERID_LocalAppData) returned " << okay); -		if (SUCCEEDED(okay) && pwstr) -		{ -			// But of course, only update mOSCacheDir if SHGetKnownFolderPath() works. -			mOSCacheDir = ll_convert_wide_to_string(pwstr); -			// Update our environment so that child processes will see a -			// reasonable value as well. -			_wputenv_s(L"LOCALAPPDATA", pwstr); -			// SHGetKnownFolderPath() contract requires us to free pwstr -			CoTaskMemFree(pwstr); -			PRELOG("mOSCacheDir='" << mOSCacheDir << "'"); -		} -	} - -	if (GetTempPath(MAX_PATH, w_str)) -	{ -		if (wcslen(w_str))	/* Flawfinder: ignore */  -		{ -			w_str[wcslen(w_str)-1] = '\0'; /* Flawfinder: ignore */ // remove trailing slash -		} -		mTempDir = utf16str_to_utf8str(llutf16string(w_str)); - -		if (mOSUserDir.empty()) -		{ -			mOSUserDir = mTempDir; -		} - -		if (mOSCacheDir.empty()) -		{ -			mOSCacheDir = mTempDir; -		} -	} -	else -	{ -		mTempDir = mOSUserDir; -	} +    // set this first: used by append() and add() methods +    mDirDelimiter = "\\"; + +    WCHAR w_str[MAX_PATH]; +    // Application Data is where user settings go. We rely on $APPDATA being +    // correct. +    auto APPDATA = LLStringUtil::getoptenv("APPDATA"); +    if (APPDATA) +    { +        mOSUserDir = *APPDATA; +    } +    PRELOG("APPDATA='" << mOSUserDir << "'"); +    // On Windows, we could have received a plain-ASCII pathname in which +    // non-ASCII characters have been munged to '?', or the pathname could +    // have been badly encoded and decoded such that we now have garbage +    // instead of a valid path. Check that mOSUserDir actually exists. +    if (mOSUserDir.empty() || ! fileExists(mOSUserDir)) +    { +        PRELOG("APPDATA does not exist"); +        //HRESULT okay = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, w_str); +        wchar_t *pwstr = NULL; +        HRESULT okay = SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &pwstr); +        PRELOG("SHGetKnownFolderPath(FOLDERID_RoamingAppData) returned " << okay); +        if (SUCCEEDED(okay) && pwstr) +        { +            // But of course, only update mOSUserDir if SHGetKnownFolderPath() works. +            mOSUserDir = ll_convert_wide_to_string(pwstr); +            // Not only that: update our environment so that child processes +            // will see a reasonable value as well. +            _wputenv_s(L"APPDATA", pwstr); +            // SHGetKnownFolderPath() contract requires us to free pwstr +            CoTaskMemFree(pwstr); +            PRELOG("mOSUserDir='" << mOSUserDir << "'"); +        } +    } + +    // We want cache files to go on the local disk, even if the +    // user is on a network with a "roaming profile". +    // +    // On Vista this is: +    //   C:\Users\James\AppData\Local +    // +    // We used to store the cache in AppData\Roaming, and the installer +    // cleans up that version on upgrade.  JC +    auto LOCALAPPDATA = LLStringUtil::getoptenv("LOCALAPPDATA"); +    if (LOCALAPPDATA) +    { +        mOSCacheDir = *LOCALAPPDATA; +    } +    PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'"); +    // Windows really does not deal well with pathnames containing non-ASCII +    // characters. See above remarks about APPDATA. +    if (mOSCacheDir.empty() || ! fileExists(mOSCacheDir)) +    { +        PRELOG("LOCALAPPDATA does not exist"); +        //HRESULT okay = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, w_str); +        wchar_t *pwstr = NULL; +        HRESULT okay = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pwstr); +        PRELOG("SHGetKnownFolderPath(FOLDERID_LocalAppData) returned " << okay); +        if (SUCCEEDED(okay) && pwstr) +        { +            // But of course, only update mOSCacheDir if SHGetKnownFolderPath() works. +            mOSCacheDir = ll_convert_wide_to_string(pwstr); +            // Update our environment so that child processes will see a +            // reasonable value as well. +            _wputenv_s(L"LOCALAPPDATA", pwstr); +            // SHGetKnownFolderPath() contract requires us to free pwstr +            CoTaskMemFree(pwstr); +            PRELOG("mOSCacheDir='" << mOSCacheDir << "'"); +        } +    } + +    if (GetTempPath(MAX_PATH, w_str)) +    { +        if (wcslen(w_str))  /* Flawfinder: ignore */ +        { +            w_str[wcslen(w_str)-1] = '\0'; /* Flawfinder: ignore */ // remove trailing slash +        } +        mTempDir = utf16str_to_utf8str(llutf16string(w_str)); + +        if (mOSUserDir.empty()) +        { +            mOSUserDir = mTempDir; +        } + +        if (mOSCacheDir.empty()) +        { +            mOSCacheDir = mTempDir; +        } +    } +    else +    { +        mTempDir = mOSUserDir; +    }  /*==========================================================================*| -	// Now that we've got mOSUserDir, one way or another, let's see how we did -	// with our environment variables. -	{ -		auto report = [this](std::ostream& out){ -			out << "mOSUserDir  = '" << mOSUserDir  << "'\n" -				<< "mOSCacheDir = '" << mOSCacheDir << "'\n" -				<< "mTempDir    = '" << mTempDir    << "'" << std::endl; -		}; -		int res = LLFile::mkdir(mOSUserDir); -		if (res == -1) -		{ -			// If we couldn't even create the directory, just blurt to stderr -			report(std::cerr); -		} -		else -		{ -			// successfully created logdir, plunk a log file there -			std::string logfilename(add(mOSUserDir, "lldir.log")); -			std::ofstream logfile(logfilename.c_str()); -			if (! logfile.is_open()) -			{ -				report(std::cerr); -			} -			else -			{ -				report(logfile); -			} -		} -	} +    // Now that we've got mOSUserDir, one way or another, let's see how we did +    // with our environment variables. +    { +        auto report = [this](std::ostream& out){ +            out << "mOSUserDir  = '" << mOSUserDir  << "'\n" +                << "mOSCacheDir = '" << mOSCacheDir << "'\n" +                << "mTempDir    = '" << mTempDir    << "'" << std::endl; +        }; +        int res = LLFile::mkdir(mOSUserDir); +        if (res == -1) +        { +            // If we couldn't even create the directory, just blurt to stderr +            report(std::cerr); +        } +        else +        { +            // successfully created logdir, plunk a log file there +            std::string logfilename(add(mOSUserDir, "lldir.log")); +            std::ofstream logfile(logfilename.c_str()); +            if (! logfile.is_open()) +            { +                report(std::cerr); +            } +            else +            { +                report(logfile); +            } +        } +    }  |*==========================================================================*/ -//	fprintf(stderr, "mTempDir = <%s>",mTempDir); - -	// Set working directory, for LLDir::getWorkingDir() -	GetCurrentDirectory(MAX_PATH, w_str); -	mWorkingDir = utf16str_to_utf8str(llutf16string(w_str)); - -	// Set the executable directory -	S32 size = GetModuleFileName(NULL, w_str, MAX_PATH); -	if (size) -	{ -		w_str[size] = '\0'; -		mExecutablePathAndName = utf16str_to_utf8str(llutf16string(w_str)); -		S32 path_end = mExecutablePathAndName.find_last_of('\\'); -		if (path_end != std::string::npos) -		{ -			mExecutableDir = mExecutablePathAndName.substr(0, path_end); -			mExecutableFilename = mExecutablePathAndName.substr(path_end+1, std::string::npos); -		} -		else -		{ -			mExecutableFilename = mExecutablePathAndName; -		} - -	} -	else -	{ -		fprintf(stderr, "Couldn't get APP path, assuming current directory!"); -		mExecutableDir = mWorkingDir; -		// Assume it's the current directory -	} - -	// mAppRODataDir = ".";	 - -	// Determine the location of the App-Read-Only-Data -	// Try the working directory then the exe's dir. -	mAppRODataDir = mWorkingDir; - - -//	if (mExecutableDir.find("indra") == std::string::npos) -	 -	// *NOTE:Mani - It is a mistake to put viewer specific code in -	// the LLDir implementation. The references to 'skins' and  -	// 'llplugin' need to go somewhere else. -	// alas... this also gets called during static initialization  -	// time due to the construction of gDirUtil in lldir.cpp. -	if(! LLFile::isdir(add(mAppRODataDir, "skins"))) -	{ -		// What? No skins in the working dir? -		// Try the executable's directory. -		mAppRODataDir = mExecutableDir; -	} - -//	LL_INFOS() << "mAppRODataDir = " << mAppRODataDir << LL_ENDL; - -	mSkinBaseDir = add(mAppRODataDir, "skins"); - -	// Build the default cache directory -	mDefaultCacheDir = buildSLOSCacheDir(); -	 -	// Make sure it exists -	int res = LLFile::mkdir(mDefaultCacheDir); -	if (res == -1) -	{ -		LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << mDefaultCacheDir << LL_ENDL; -	} - -	mLLPluginDir = add(mExecutableDir, "llplugin"); +//  fprintf(stderr, "mTempDir = <%s>",mTempDir); + +    // Set working directory, for LLDir::getWorkingDir() +    GetCurrentDirectory(MAX_PATH, w_str); +    mWorkingDir = utf16str_to_utf8str(llutf16string(w_str)); + +    // Set the executable directory +    S32 size = GetModuleFileName(NULL, w_str, MAX_PATH); +    if (size) +    { +        w_str[size] = '\0'; +        mExecutablePathAndName = utf16str_to_utf8str(llutf16string(w_str)); +        S32 path_end = mExecutablePathAndName.find_last_of('\\'); +        if (path_end != std::string::npos) +        { +            mExecutableDir = mExecutablePathAndName.substr(0, path_end); +            mExecutableFilename = mExecutablePathAndName.substr(path_end+1, std::string::npos); +        } +        else +        { +            mExecutableFilename = mExecutablePathAndName; +        } + +    } +    else +    { +        fprintf(stderr, "Couldn't get APP path, assuming current directory!"); +        mExecutableDir = mWorkingDir; +        // Assume it's the current directory +    } + +    // mAppRODataDir = "."; + +    // Determine the location of the App-Read-Only-Data +    // Try the working directory then the exe's dir. +    mAppRODataDir = mWorkingDir; + + +//  if (mExecutableDir.find("indra") == std::string::npos) + +    // *NOTE:Mani - It is a mistake to put viewer specific code in +    // the LLDir implementation. The references to 'skins' and +    // 'llplugin' need to go somewhere else. +    // alas... this also gets called during static initialization +    // time due to the construction of gDirUtil in lldir.cpp. +    if(! LLFile::isdir(add(mAppRODataDir, "skins"))) +    { +        // What? No skins in the working dir? +        // Try the executable's directory. +        mAppRODataDir = mExecutableDir; +    } + +//  LL_INFOS() << "mAppRODataDir = " << mAppRODataDir << LL_ENDL; + +    mSkinBaseDir = add(mAppRODataDir, "skins"); + +    // Build the default cache directory +    mDefaultCacheDir = buildSLOSCacheDir(); + +    // Make sure it exists +    int res = LLFile::mkdir(mDefaultCacheDir); +    if (res == -1) +    { +        LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << mDefaultCacheDir << LL_ENDL; +    } + +    mLLPluginDir = add(mExecutableDir, "llplugin");  }  LLDir_Win32::~LLDir_Win32() @@ -297,110 +297,110 @@ LLDir_Win32::~LLDir_Win32()  // Implementation  void LLDir_Win32::initAppDirs(const std::string &app_name, -							  const std::string& app_read_only_data_dir) +                              const std::string& app_read_only_data_dir)  { -	// Allow override so test apps can read newview directory -	if (!app_read_only_data_dir.empty()) -	{ -		mAppRODataDir = app_read_only_data_dir; -		mSkinBaseDir = add(mAppRODataDir, "skins"); -	} -	mAppName = app_name; -	mOSUserAppDir = add(mOSUserDir, app_name); - -	int res = LLFile::mkdir(mOSUserAppDir); -	if (res == -1) -	{ -		LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL; -		LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL; -		mOSUserAppDir = mOSUserDir; -	} -	//dumpCurrentDirectories(); - -	res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"")); -	if (res == -1) -	{ -		LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL; -	} - -	res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"")); -	if (res == -1) -	{ -		LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL; -	} - -	res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"")); -	if (res == -1) -	{ -		LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; -	} - -	mCAFile = getExpandedFilename( LL_PATH_EXECUTABLE, "ca-bundle.crt" ); +    // Allow override so test apps can read newview directory +    if (!app_read_only_data_dir.empty()) +    { +        mAppRODataDir = app_read_only_data_dir; +        mSkinBaseDir = add(mAppRODataDir, "skins"); +    } +    mAppName = app_name; +    mOSUserAppDir = add(mOSUserDir, app_name); + +    int res = LLFile::mkdir(mOSUserAppDir); +    if (res == -1) +    { +        LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL; +        LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL; +        mOSUserAppDir = mOSUserDir; +    } +    //dumpCurrentDirectories(); + +    res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"")); +    if (res == -1) +    { +        LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL; +    } + +    res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"")); +    if (res == -1) +    { +        LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL; +    } + +    res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"")); +    if (res == -1) +    { +        LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; +    } + +    mCAFile = getExpandedFilename( LL_PATH_EXECUTABLE, "ca-bundle.crt" );  }  U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &mask)  { -	HANDLE count_search_h; -	U32 file_count; +    HANDLE count_search_h; +    U32 file_count; -	file_count = 0; +    file_count = 0; -	WIN32_FIND_DATA FileData; +    WIN32_FIND_DATA FileData; -	llutf16string pathname = utf8str_to_utf16str(dirname); -	pathname += utf8str_to_utf16str(mask); -	 -	if ((count_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)    -	{ -		file_count++; +    llutf16string pathname = utf8str_to_utf16str(dirname); +    pathname += utf8str_to_utf16str(mask); -		while (FindNextFile(count_search_h, &FileData)) -		{ -			file_count++; -		} -		    -		FindClose(count_search_h); -	} +    if ((count_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE) +    { +        file_count++; -	return (file_count); +        while (FindNextFile(count_search_h, &FileData)) +        { +            file_count++; +        } + +        FindClose(count_search_h); +    } + +    return (file_count);  }  std::string LLDir_Win32::getCurPath()  { -	WCHAR w_str[MAX_PATH]; -	GetCurrentDirectory(MAX_PATH, w_str); +    WCHAR w_str[MAX_PATH]; +    GetCurrentDirectory(MAX_PATH, w_str); -	return utf16str_to_utf8str(llutf16string(w_str)); +    return utf16str_to_utf8str(llutf16string(w_str));  }  bool LLDir_Win32::fileExists(const std::string &filename) const  { -	llstat stat_data; -	// Check the age of the file -	// Now, we see if the files we've gathered are recent... -	int res = LLFile::stat(filename, &stat_data); -	if (!res) -	{ -		return true; -	} -	else -	{ -		return false; -	} +    llstat stat_data; +    // Check the age of the file +    // Now, we see if the files we've gathered are recent... +    int res = LLFile::stat(filename, &stat_data); +    if (!res) +    { +        return true; +    } +    else +    { +        return false; +    }  }  /*virtual*/ std::string LLDir_Win32::getLLPluginLauncher()  { -	return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + -		"SLPlugin.exe"; +    return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + +        "SLPlugin.exe";  }  /*virtual*/ std::string LLDir_Win32::getLLPluginFilename(std::string base_name)  { -	return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + -		base_name + ".dll"; +    return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + +        base_name + ".dll";  } @@ -415,8 +415,8 @@ DWORD GetDllVersion(LPCTSTR lpszDllName)      HINSTANCE hinstDll;      DWORD dwVersion = 0; -    hinstDll = LoadLibrary(lpszDllName);	/* Flawfinder: ignore */  -	 +    hinstDll = LoadLibrary(lpszDllName);    /* Flawfinder: ignore */ +      if(hinstDll)      {          DLLGETVERSIONPROC pDllGetVersion; @@ -424,7 +424,7 @@ DWORD GetDllVersion(LPCTSTR lpszDllName)          pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion");  /*Because some DLLs might not implement this function, you -  must test for it explicitly. Depending on the particular  +  must test for it explicitly. Depending on the particular    DLL, the lack of a DllGetVersion function can be a useful    indicator of the version.  */ @@ -443,7 +443,7 @@ DWORD GetDllVersion(LPCTSTR lpszDllName)                  dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion);              }          } -         +          FreeLibrary(hinstDll);      }      return dwVersion; diff --git a/indra/llfilesystem/lldir_win32.h b/indra/llfilesystem/lldir_win32.h index fa6d5fd320..ab2726f1a0 100644 --- a/indra/llfilesystem/lldir_win32.h +++ b/indra/llfilesystem/lldir_win32.h @@ -1,25 +1,25 @@ -/**  +/**   * @file lldir_win32.h   * @brief Definition of directory utilities class for windows   *   * $LicenseInfo:firstyear=2000&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -36,22 +36,22 @@  class LLDir_Win32 : public LLDir  {  public: -	LLDir_Win32(); -	virtual ~LLDir_Win32(); +    LLDir_Win32(); +    virtual ~LLDir_Win32(); -	/*virtual*/ void initAppDirs(const std::string &app_name, -		const std::string& app_read_only_data_dir); +    /*virtual*/ void initAppDirs(const std::string &app_name, +        const std::string& app_read_only_data_dir); -	/*virtual*/ std::string getCurPath(); -	/*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask); -	/*virtual*/ bool fileExists(const std::string &filename) const; +    /*virtual*/ std::string getCurPath(); +    /*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask); +    /*virtual*/ bool fileExists(const std::string &filename) const; -	/*virtual*/ std::string getLLPluginLauncher(); -	/*virtual*/ std::string getLLPluginFilename(std::string base_name); +    /*virtual*/ std::string getLLPluginLauncher(); +    /*virtual*/ std::string getLLPluginFilename(std::string base_name);  private: -	void* mDirSearch_h{ nullptr }; -	llutf16string mCurrentDir; +    void* mDirSearch_h{ nullptr }; +    llutf16string mCurrentDir;  };  #endif // LL_LLDIR_WIN32_H diff --git a/indra/llfilesystem/lldirguard.h b/indra/llfilesystem/lldirguard.h index 37b9e9b83e..fcb179bbc8 100644 --- a/indra/llfilesystem/lldirguard.h +++ b/indra/llfilesystem/lldirguard.h @@ -1,25 +1,25 @@ -/**  +/**   * @file lldirguard.h   * @brief Protect working directory from being changed in scope.   *   * $LicenseInfo:firstyear=2009&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -34,39 +34,39 @@  class LLDirectoryGuard  {  public: -	LLDirectoryGuard() -	{ -		mOrigDirLen = GetCurrentDirectory(MAX_PATH, mOrigDir); -	} +    LLDirectoryGuard() +    { +        mOrigDirLen = GetCurrentDirectory(MAX_PATH, mOrigDir); +    } -	~LLDirectoryGuard() -	{ -		mFinalDirLen = GetCurrentDirectory(MAX_PATH, mFinalDir); -		if ((mOrigDirLen!=mFinalDirLen) || -			(wcsncmp(mOrigDir,mFinalDir,mOrigDirLen)!=0)) -		{ -			// Dir has changed -			std::string mOrigDirUtf8 = utf16str_to_utf8str(llutf16string(mOrigDir)); -			std::string mFinalDirUtf8 = utf16str_to_utf8str(llutf16string(mFinalDir)); -			LL_INFOS() << "Resetting working dir from " << mFinalDirUtf8 << " to " << mOrigDirUtf8 << LL_ENDL; -			SetCurrentDirectory(mOrigDir); -		} -	} +    ~LLDirectoryGuard() +    { +        mFinalDirLen = GetCurrentDirectory(MAX_PATH, mFinalDir); +        if ((mOrigDirLen!=mFinalDirLen) || +            (wcsncmp(mOrigDir,mFinalDir,mOrigDirLen)!=0)) +        { +            // Dir has changed +            std::string mOrigDirUtf8 = utf16str_to_utf8str(llutf16string(mOrigDir)); +            std::string mFinalDirUtf8 = utf16str_to_utf8str(llutf16string(mFinalDir)); +            LL_INFOS() << "Resetting working dir from " << mFinalDirUtf8 << " to " << mOrigDirUtf8 << LL_ENDL; +            SetCurrentDirectory(mOrigDir); +        } +    }  private: -	TCHAR mOrigDir[MAX_PATH]; -	DWORD mOrigDirLen; -	TCHAR mFinalDir[MAX_PATH]; -	DWORD mFinalDirLen; +    TCHAR mOrigDir[MAX_PATH]; +    DWORD mOrigDirLen; +    TCHAR mFinalDir[MAX_PATH]; +    DWORD mFinalDirLen;  };  #else // No-op outside Windows.  class LLDirectoryGuard  {  public: -	LLDirectoryGuard() {} -	~LLDirectoryGuard() {} +    LLDirectoryGuard() {} +    ~LLDirectoryGuard() {}  }; -#endif  +#endif  #endif diff --git a/indra/llfilesystem/lldiriterator.cpp b/indra/llfilesystem/lldiriterator.cpp index f57bf4ebc6..61f768c512 100644 --- a/indra/llfilesystem/lldiriterator.cpp +++ b/indra/llfilesystem/lldiriterator.cpp @@ -37,74 +37,74 @@ static std::string glob_to_regex(const std::string& glob);  class LLDirIterator::Impl  {  public: -	Impl(const std::string &dirname, const std::string &mask); -	~Impl(); +    Impl(const std::string &dirname, const std::string &mask); +    ~Impl(); -	bool next(std::string &fname); +    bool next(std::string &fname);  private: -	boost::regex			mFilterExp; -	fs::directory_iterator	mIter; -	bool					mIsValid; +    boost::regex            mFilterExp; +    fs::directory_iterator  mIter; +    bool                    mIsValid;  };  LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) -	: mIsValid(false) +    : mIsValid(false)  {  #ifdef LL_WINDOWS // or BOOST_WINDOWS_API -	fs::path dir_path(utf8str_to_utf16str(dirname)); +    fs::path dir_path(utf8str_to_utf16str(dirname));  #else -	fs::path dir_path(dirname); +    fs::path dir_path(dirname);  #endif -	bool is_dir = false; - -	// Check if path is a directory. -	try -	{ -		is_dir = fs::is_directory(dir_path); -	} -	catch (const fs::filesystem_error& e) -	{ -		LL_WARNS() << e.what() << LL_ENDL; -		return; -	} - -	if (!is_dir) -	{ -		LL_WARNS() << "Invalid path: \"" << dir_path.string() << "\"" << LL_ENDL; -		return; -	} - -	// Initialize the directory iterator for the given path. -	try -	{ -		mIter = fs::directory_iterator(dir_path); -	} -	catch (const fs::filesystem_error& e) -	{ -		LL_WARNS() << e.what() << LL_ENDL; -		return; -	} - -	// Convert the glob mask to a regular expression -	std::string exp = glob_to_regex(mask); - -	// Initialize boost::regex with the expression converted from -	// the glob mask. -	// An exception is thrown if the expression is not valid. -	try -	{ -		mFilterExp.assign(exp); -	} -	catch (boost::regex_error& e) -	{ -		LL_WARNS() << "\"" << exp << "\" is not a valid regular expression: " -				<< e.what() << LL_ENDL; -		return; -	} - -	mIsValid = true; +    bool is_dir = false; + +    // Check if path is a directory. +    try +    { +        is_dir = fs::is_directory(dir_path); +    } +    catch (const fs::filesystem_error& e) +    { +        LL_WARNS() << e.what() << LL_ENDL; +        return; +    } + +    if (!is_dir) +    { +        LL_WARNS() << "Invalid path: \"" << dir_path.string() << "\"" << LL_ENDL; +        return; +    } + +    // Initialize the directory iterator for the given path. +    try +    { +        mIter = fs::directory_iterator(dir_path); +    } +    catch (const fs::filesystem_error& e) +    { +        LL_WARNS() << e.what() << LL_ENDL; +        return; +    } + +    // Convert the glob mask to a regular expression +    std::string exp = glob_to_regex(mask); + +    // Initialize boost::regex with the expression converted from +    // the glob mask. +    // An exception is thrown if the expression is not valid. +    try +    { +        mFilterExp.assign(exp); +    } +    catch (boost::regex_error& e) +    { +        LL_WARNS() << "\"" << exp << "\" is not a valid regular expression: " +                << e.what() << LL_ENDL; +        return; +    } + +    mIsValid = true;  }  LLDirIterator::Impl::~Impl() @@ -113,39 +113,39 @@ LLDirIterator::Impl::~Impl()  bool LLDirIterator::Impl::next(std::string &fname)  { -	fname = ""; - -	if (!mIsValid) -	{ -		LL_WARNS() << "The iterator is not correctly initialized." << LL_ENDL; -		return false; -	} - -	fs::directory_iterator end_itr; // default construction yields past-the-end -	bool found = false; - -	// Check if path is a directory. -	try -	{ -		while (mIter != end_itr && !found) -		{ -			boost::smatch match; -			std::string name = mIter->path().filename().string(); -			found = ll_regex_match(name, match, mFilterExp); -			if (found) -			{ -				fname = name; -			} - -			++mIter; -		} -	} -	catch (const fs::filesystem_error& e) -	{ -		LL_WARNS() << e.what() << LL_ENDL; -	} - -	return found; +    fname = ""; + +    if (!mIsValid) +    { +        LL_WARNS() << "The iterator is not correctly initialized." << LL_ENDL; +        return false; +    } + +    fs::directory_iterator end_itr; // default construction yields past-the-end +    bool found = false; + +    // Check if path is a directory. +    try +    { +        while (mIter != end_itr && !found) +        { +            boost::smatch match; +            std::string name = mIter->path().filename().string(); +            found = ll_regex_match(name, match, mFilterExp); +            if (found) +            { +                fname = name; +            } + +            ++mIter; +        } +    } +    catch (const fs::filesystem_error& e) +    { +        LL_WARNS() << e.what() << LL_ENDL; +    } + +    return found;  }  /** @@ -153,91 +153,91 @@ Converts the incoming glob into a regex. This involves  converting incoming glob expressions to regex equivilents and  at the same time, escaping any regex meaningful characters which  do not have glob meaning, i.e. -            .()+|^$  +            .()+|^$  in the input.  */  std::string glob_to_regex(const std::string& glob)  { -	std::string regex; -	regex.reserve(glob.size()<<1); -	S32 braces = 0; -	bool escaped = false; -	bool square_brace_open = false; - -	for (std::string::const_iterator i = glob.begin(); i != glob.end(); ++i) -	{ -		char c = *i; - -		switch (c) -		{ -			case '*': -				if (glob.begin() == i) -				{ -					regex+="[^.].*"; -				} -				else -				{ -					regex+= escaped ? "*" : ".*"; -				} -				break; -			case '?': -				regex+= escaped ? '?' : '.'; -				break; -			case '{': -				braces++; -				regex+='('; -				break; -			case '}': -				if (!braces) -				{ -					LL_ERRS() << "glob_to_regex: Closing brace without an equivalent opening brace: " << glob << LL_ENDL; -				} - -				regex+=')'; -				braces--; -				break; -			case ',': -				regex+= braces ? '|' : c; -				break; -			case '!': -				regex+= square_brace_open ? '^' : c; -				break; -			case '.': // This collection have different regex meaning -			case '^': // and so need escaping. -			case '(':  -			case ')': -			case '+': -			case '|': -			case '$': -				regex += '\\';  -			default: -				regex += c; -				break; -		} - -		escaped = ('\\' == c); -		square_brace_open = ('[' == c); -	} - -	if (braces) -	{ -		LL_ERRS() << "glob_to_regex: Unterminated brace expression: " << glob << LL_ENDL; -	} - -	return regex; +    std::string regex; +    regex.reserve(glob.size()<<1); +    S32 braces = 0; +    bool escaped = false; +    bool square_brace_open = false; + +    for (std::string::const_iterator i = glob.begin(); i != glob.end(); ++i) +    { +        char c = *i; + +        switch (c) +        { +            case '*': +                if (glob.begin() == i) +                { +                    regex+="[^.].*"; +                } +                else +                { +                    regex+= escaped ? "*" : ".*"; +                } +                break; +            case '?': +                regex+= escaped ? '?' : '.'; +                break; +            case '{': +                braces++; +                regex+='('; +                break; +            case '}': +                if (!braces) +                { +                    LL_ERRS() << "glob_to_regex: Closing brace without an equivalent opening brace: " << glob << LL_ENDL; +                } + +                regex+=')'; +                braces--; +                break; +            case ',': +                regex+= braces ? '|' : c; +                break; +            case '!': +                regex+= square_brace_open ? '^' : c; +                break; +            case '.': // This collection have different regex meaning +            case '^': // and so need escaping. +            case '(': +            case ')': +            case '+': +            case '|': +            case '$': +                regex += '\\'; +            default: +                regex += c; +                break; +        } + +        escaped = ('\\' == c); +        square_brace_open = ('[' == c); +    } + +    if (braces) +    { +        LL_ERRS() << "glob_to_regex: Unterminated brace expression: " << glob << LL_ENDL; +    } + +    return regex;  }  LLDirIterator::LLDirIterator(const std::string &dirname, const std::string &mask)  { -	mImpl = new Impl(dirname, mask); +    mImpl = new Impl(dirname, mask);  }  LLDirIterator::~LLDirIterator()  { -	delete mImpl; +    delete mImpl;  }  bool LLDirIterator::next(std::string &fname)  { -	return mImpl->next(fname); +    return mImpl->next(fname);  } diff --git a/indra/llfilesystem/lldiriterator.h b/indra/llfilesystem/lldiriterator.h index 0b48be41b3..31d8349b7f 100644 --- a/indra/llfilesystem/lldiriterator.h +++ b/indra/llfilesystem/lldiriterator.h @@ -37,51 +37,51 @@  class LLDirIterator  {  public: -	/** -	 * Constructs LLDirIterator object to search for glob pattern -	 * matches in a directory. -	 * -	 * @param dirname - name of a directory to search in. -	 * @param mask - search pattern, a glob expression -	 * -	 * Wildcards supported in glob expressions: -	 * -------------------------------------------------------------- -	 * | Wildcard 	| Matches										| -	 * -------------------------------------------------------------- -	 * | 	* 		|zero or more characters						| -	 * | 	?		|exactly one character							| -	 * | [abcde]	|exactly one character listed					| -	 * | [a-e]		|exactly one character in the given range		| -	 * | [!abcde]	|any character that is not listed				| -	 * | [!a-e]		|any character that is not in the given range	| -	 * | {abc,xyz}	|exactly one entire word in the options given	| -	 * -------------------------------------------------------------- -	 */ -	LLDirIterator(const std::string &dirname, const std::string &mask); +    /** +     * Constructs LLDirIterator object to search for glob pattern +     * matches in a directory. +     * +     * @param dirname - name of a directory to search in. +     * @param mask - search pattern, a glob expression +     * +     * Wildcards supported in glob expressions: +     * -------------------------------------------------------------- +     * | Wildcard   | Matches                                       | +     * -------------------------------------------------------------- +     * |    *       |zero or more characters                        | +     * |    ?       |exactly one character                          | +     * | [abcde]    |exactly one character listed                   | +     * | [a-e]      |exactly one character in the given range       | +     * | [!abcde]   |any character that is not listed               | +     * | [!a-e]     |any character that is not in the given range   | +     * | {abc,xyz}  |exactly one entire word in the options given   | +     * -------------------------------------------------------------- +     */ +    LLDirIterator(const std::string &dirname, const std::string &mask); -	~LLDirIterator(); +    ~LLDirIterator(); -	/** -	 * Searches for the next directory entry matching the glob mask -	 * specified upon iterator construction. -	 * Returns true if a match is found, sets fname -	 * parameter to the name of the matched directory entry and -	 * increments the iterator position. -	 * -	 * Typical usage: -	 * <code> -	 * LLDirIterator iter(directory, pattern); -	 * if ( iter.next(scanResult) ) -	 * </code> -	 * -	 * @param fname - name of the matched directory entry. -	 * @return true if a match is found, false otherwise. -	 */ -	bool next(std::string &fname); +    /** +     * Searches for the next directory entry matching the glob mask +     * specified upon iterator construction. +     * Returns true if a match is found, sets fname +     * parameter to the name of the matched directory entry and +     * increments the iterator position. +     * +     * Typical usage: +     * <code> +     * LLDirIterator iter(directory, pattern); +     * if ( iter.next(scanResult) ) +     * </code> +     * +     * @param fname - name of the matched directory entry. +     * @return true if a match is found, false otherwise. +     */ +    bool next(std::string &fname);  protected: -	class Impl; -	Impl* mImpl; +    class Impl; +    Impl* mImpl;  };  #endif //LL_LLDIRITERATOR_H diff --git a/indra/llfilesystem/lllfsthread.cpp b/indra/llfilesystem/lllfsthread.cpp index dbb69cd605..7d135b4472 100644 --- a/indra/llfilesystem/lllfsthread.cpp +++ b/indra/llfilesystem/lllfsthread.cpp @@ -1,25 +1,25 @@ -/**  +/**   * @file lllfsthread.cpp   * @brief LLLFSThread base class   *   * $LicenseInfo:firstyear=2001&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -38,112 +38,112 @@  //static  void LLLFSThread::initClass(bool local_is_threaded)  { -	llassert(sLocal == NULL); -	sLocal = new LLLFSThread(local_is_threaded); +    llassert(sLocal == NULL); +    sLocal = new LLLFSThread(local_is_threaded);  }  //static  S32 LLLFSThread::updateClass(U32 ms_elapsed)  { -	return sLocal->update((F32)ms_elapsed); +    return sLocal->update((F32)ms_elapsed);  }  //static  void LLLFSThread::cleanupClass()  { -	llassert(sLocal != NULL); -	sLocal->setQuitting(); -	while (sLocal->getPending()) -	{ -		sLocal->update(0); -	} +    llassert(sLocal != NULL); +    sLocal->setQuitting(); +    while (sLocal->getPending()) +    { +        sLocal->update(0); +    }      sLocal->shutdown(); -	delete sLocal; -	sLocal = NULL; +    delete sLocal; +    sLocal = NULL;  }  //----------------------------------------------------------------------------  LLLFSThread::LLLFSThread(bool threaded) : -	LLQueuedThread("LFS", threaded) +    LLQueuedThread("LFS", threaded)  { -	if(!mLocalAPRFilePoolp) -	{ -		mLocalAPRFilePoolp = new LLVolatileAPRPool() ; -	} +    if(!mLocalAPRFilePoolp) +    { +        mLocalAPRFilePoolp = new LLVolatileAPRPool() ; +    }  }  LLLFSThread::~LLLFSThread()  { -	// mLocalAPRFilePoolp cleanup in LLThread -	// ~LLQueuedThread() will be called here +    // mLocalAPRFilePoolp cleanup in LLThread +    // ~LLQueuedThread() will be called here  }  //---------------------------------------------------------------------------- -LLLFSThread::handle_t LLLFSThread::read(const std::string& filename,	/* Flawfinder: ignore */  -										U8* buffer, S32 offset, S32 numbytes, -										Responder* responder) +LLLFSThread::handle_t LLLFSThread::read(const std::string& filename,    /* Flawfinder: ignore */ +                                        U8* buffer, S32 offset, S32 numbytes, +                                        Responder* responder)  {      LL_PROFILE_ZONE_SCOPED; -	handle_t handle = generateHandle(); +    handle_t handle = generateHandle(); -	Request* req = new Request(this, handle, -							   FILE_READ, filename, -							   buffer, offset, numbytes, -							   responder); +    Request* req = new Request(this, handle, +                               FILE_READ, filename, +                               buffer, offset, numbytes, +                               responder); -	bool res = addRequest(req); -	if (!res) -	{ -		LL_ERRS() << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << LL_ENDL; -	} +    bool res = addRequest(req); +    if (!res) +    { +        LL_ERRS() << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << LL_ENDL; +    } -	return handle; +    return handle;  }  LLLFSThread::handle_t LLLFSThread::write(const std::string& filename, -										 U8* buffer, S32 offset, S32 numbytes, -										 Responder* responder) +                                         U8* buffer, S32 offset, S32 numbytes, +                                         Responder* responder)  {      LL_PROFILE_ZONE_SCOPED; -	handle_t handle = generateHandle(); - -	Request* req = new Request(this, handle, -							   FILE_WRITE, filename, -							   buffer, offset, numbytes, -							   responder); - -	bool res = addRequest(req); -	if (!res) -	{ -		LL_ERRS() << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << LL_ENDL; -	} -	 -	return handle; +    handle_t handle = generateHandle(); + +    Request* req = new Request(this, handle, +                               FILE_WRITE, filename, +                               buffer, offset, numbytes, +                               responder); + +    bool res = addRequest(req); +    if (!res) +    { +        LL_ERRS() << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << LL_ENDL; +    } + +    return handle;  }  //============================================================================  LLLFSThread::Request::Request(LLLFSThread* thread, -							  handle_t handle, -							  operation_t op, const std::string& filename, -							  U8* buffer, S32 offset, S32 numbytes, -							  Responder* responder) : -	QueuedRequest(handle, FLAG_AUTO_COMPLETE), -	mThread(thread), -	mOperation(op), -	mFileName(filename), -	mBuffer(buffer), -	mOffset(offset), -	mBytes(numbytes), -	mBytesRead(0), -	mResponder(responder) +                              handle_t handle, +                              operation_t op, const std::string& filename, +                              U8* buffer, S32 offset, S32 numbytes, +                              Responder* responder) : +    QueuedRequest(handle, FLAG_AUTO_COMPLETE), +    mThread(thread), +    mOperation(op), +    mFileName(filename), +    mBuffer(buffer), +    mOffset(offset), +    mBytes(numbytes), +    mBytesRead(0), +    mResponder(responder)  { -	if (numbytes <= 0) -	{ -		LL_WARNS() << "LLLFSThread: Request with numbytes = " << numbytes << LL_ENDL; -	} +    if (numbytes <= 0) +    { +        LL_WARNS() << "LLLFSThread: Request with numbytes = " << numbytes << LL_ENDL; +    }  }  LLLFSThread::Request::~Request() @@ -154,85 +154,85 @@ LLLFSThread::Request::~Request()  void LLLFSThread::Request::finishRequest(bool completed)  {      LL_PROFILE_ZONE_SCOPED; -	if (mResponder.notNull()) -	{ -		mResponder->completed(completed ? mBytesRead : 0); -		mResponder = NULL; -	} +    if (mResponder.notNull()) +    { +        mResponder->completed(completed ? mBytesRead : 0); +        mResponder = NULL; +    }  }  void LLLFSThread::Request::deleteRequest()  {      LL_PROFILE_ZONE_SCOPED; -	if (getStatus() == STATUS_QUEUED) -	{ -		LL_ERRS() << "Attempt to delete a queued LLLFSThread::Request!" << LL_ENDL; -	}	 -	if (mResponder.notNull()) -	{ -		mResponder->completed(0); -		mResponder = NULL; -	} -	LLQueuedThread::QueuedRequest::deleteRequest(); +    if (getStatus() == STATUS_QUEUED) +    { +        LL_ERRS() << "Attempt to delete a queued LLLFSThread::Request!" << LL_ENDL; +    } +    if (mResponder.notNull()) +    { +        mResponder->completed(0); +        mResponder = NULL; +    } +    LLQueuedThread::QueuedRequest::deleteRequest();  }  bool LLLFSThread::Request::processRequest()  {      LL_PROFILE_ZONE_SCOPED; -	bool complete = false; -	if (mOperation ==  FILE_READ) -	{ -		llassert(mOffset >= 0); -		LLAPRFile infile ; // auto-closes -		infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool()); -		if (!infile.getFileHandle()) -		{ -			LL_WARNS() << "LLLFS: Unable to read file: " << mFileName << LL_ENDL; -			mBytesRead = 0; // fail -			return true; -		} -		S32 off; -		if (mOffset < 0) -			off = infile.seek(APR_END, 0); -		else -			off = infile.seek(APR_SET, mOffset); -		llassert_always(off >= 0); -		mBytesRead = infile.read(mBuffer, mBytes ); -		complete = true; -// 		LL_INFOS() << "LLLFSThread::READ:" << mFileName << " Bytes: " << mBytesRead << LL_ENDL; -	} -	else if (mOperation ==  FILE_WRITE) -	{ -		apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; -		if (mOffset < 0) -			flags |= APR_APPEND; -		LLAPRFile outfile ; // auto-closes -		outfile.open(mFileName, flags, mThread->getLocalAPRFilePool()); -		if (!outfile.getFileHandle()) -		{ -			LL_WARNS() << "LLLFS: Unable to write file: " << mFileName << LL_ENDL; -			mBytesRead = 0; // fail -			return true; -		} -		if (mOffset >= 0) -		{ -			S32 seek = outfile.seek(APR_SET, mOffset); -			if (seek < 0) -			{ -				LL_WARNS() << "LLLFS: Unable to write file (seek failed): " << mFileName << LL_ENDL; -				mBytesRead = 0; // fail -				return true; -			} -		} -		mBytesRead = outfile.write(mBuffer, mBytes ); -		complete = true; -// 		LL_INFOS() << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << LL_ENDL; -	} -	else -	{ -		LL_ERRS() << "LLLFSThread::unknown operation: " << (S32)mOperation << LL_ENDL; -	} -	return complete; +    bool complete = false; +    if (mOperation ==  FILE_READ) +    { +        llassert(mOffset >= 0); +        LLAPRFile infile ; // auto-closes +        infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool()); +        if (!infile.getFileHandle()) +        { +            LL_WARNS() << "LLLFS: Unable to read file: " << mFileName << LL_ENDL; +            mBytesRead = 0; // fail +            return true; +        } +        S32 off; +        if (mOffset < 0) +            off = infile.seek(APR_END, 0); +        else +            off = infile.seek(APR_SET, mOffset); +        llassert_always(off >= 0); +        mBytesRead = infile.read(mBuffer, mBytes ); +        complete = true; +//      LL_INFOS() << "LLLFSThread::READ:" << mFileName << " Bytes: " << mBytesRead << LL_ENDL; +    } +    else if (mOperation ==  FILE_WRITE) +    { +        apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; +        if (mOffset < 0) +            flags |= APR_APPEND; +        LLAPRFile outfile ; // auto-closes +        outfile.open(mFileName, flags, mThread->getLocalAPRFilePool()); +        if (!outfile.getFileHandle()) +        { +            LL_WARNS() << "LLLFS: Unable to write file: " << mFileName << LL_ENDL; +            mBytesRead = 0; // fail +            return true; +        } +        if (mOffset >= 0) +        { +            S32 seek = outfile.seek(APR_SET, mOffset); +            if (seek < 0) +            { +                LL_WARNS() << "LLLFS: Unable to write file (seek failed): " << mFileName << LL_ENDL; +                mBytesRead = 0; // fail +                return true; +            } +        } +        mBytesRead = outfile.write(mBuffer, mBytes ); +        complete = true; +//      LL_INFOS() << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << LL_ENDL; +    } +    else +    { +        LL_ERRS() << "LLLFSThread::unknown operation: " << (S32)mOperation << LL_ENDL; +    } +    return complete;  }  //============================================================================ diff --git a/indra/llfilesystem/lllfsthread.h b/indra/llfilesystem/lllfsthread.h index 3038e1be12..c0ed1931bb 100644 --- a/indra/llfilesystem/lllfsthread.h +++ b/indra/llfilesystem/lllfsthread.h @@ -1,25 +1,25 @@ -/**  +/**   * @file lllfsthread.h   * @brief LLLFSThread base class   *   * $LicenseInfo:firstyear=2000&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -41,97 +41,97 @@  class LLLFSThread : public LLQueuedThread  { -	//------------------------------------------------------------------------ +    //------------------------------------------------------------------------  public: -	enum operation_t { -		FILE_READ, -		FILE_WRITE, -		FILE_RENAME, -		FILE_REMOVE -	}; - -	//------------------------------------------------------------------------ +    enum operation_t { +        FILE_READ, +        FILE_WRITE, +        FILE_RENAME, +        FILE_REMOVE +    }; + +    //------------------------------------------------------------------------  public: -	class Responder : public LLThreadSafeRefCount -	{ -	protected: -		~Responder(); -	public: -		virtual void completed(S32 bytes) = 0; -	}; - -	class Request : public QueuedRequest -	{ -	protected: -		virtual ~Request(); // use deleteRequest() -		 -	public: -		Request(LLLFSThread* thread, -				handle_t handle, -				operation_t op, const std::string& filename, -				U8* buffer, S32 offset, S32 numbytes, -				Responder* responder); - -		S32 getBytes() -		{ -			return mBytes; -		} -		S32 getBytesRead() -		{ -			return mBytesRead; -		} -		S32 getOperation() -		{ -			return mOperation; -		} -		U8* getBuffer() -		{ -			return mBuffer; -		} -		const std::string& getFilename() -		{ -			return mFileName; -		} -		 -		/*virtual*/ bool processRequest(); -		/*virtual*/ void finishRequest(bool completed); -		/*virtual*/ void deleteRequest(); -		 -	private: -		LLLFSThread* mThread; -		operation_t mOperation; -		 -		std::string mFileName; -		 -		U8* mBuffer;	// dest for reads, source for writes, new UUID for rename -		S32 mOffset;	// offset into file, -1 = append (WRITE only) -		S32 mBytes;		// bytes to read from file, -1 = all -		S32 mBytesRead;	// bytes read from file - -		LLPointer<Responder> mResponder; -	}; - -	//------------------------------------------------------------------------ +    class Responder : public LLThreadSafeRefCount +    { +    protected: +        ~Responder(); +    public: +        virtual void completed(S32 bytes) = 0; +    }; + +    class Request : public QueuedRequest +    { +    protected: +        virtual ~Request(); // use deleteRequest() + +    public: +        Request(LLLFSThread* thread, +                handle_t handle, +                operation_t op, const std::string& filename, +                U8* buffer, S32 offset, S32 numbytes, +                Responder* responder); + +        S32 getBytes() +        { +            return mBytes; +        } +        S32 getBytesRead() +        { +            return mBytesRead; +        } +        S32 getOperation() +        { +            return mOperation; +        } +        U8* getBuffer() +        { +            return mBuffer; +        } +        const std::string& getFilename() +        { +            return mFileName; +        } + +        /*virtual*/ bool processRequest(); +        /*virtual*/ void finishRequest(bool completed); +        /*virtual*/ void deleteRequest(); + +    private: +        LLLFSThread* mThread; +        operation_t mOperation; + +        std::string mFileName; + +        U8* mBuffer;    // dest for reads, source for writes, new UUID for rename +        S32 mOffset;    // offset into file, -1 = append (WRITE only) +        S32 mBytes;     // bytes to read from file, -1 = all +        S32 mBytesRead; // bytes read from file + +        LLPointer<Responder> mResponder; +    }; + +    //------------------------------------------------------------------------  public: -	LLLFSThread(bool threaded = true); -	~LLLFSThread(); - -	// Return a Request handle -	handle_t read(const std::string& filename,	/* Flawfinder: ignore */  -				  U8* buffer, S32 offset, S32 numbytes, -				  Responder* responder); -	handle_t write(const std::string& filename, -				   U8* buffer, S32 offset, S32 numbytes, -				   Responder* responder); -	 -	// static initializers -	static void initClass(bool local_is_threaded = true); // Setup sLocal -	static S32 updateClass(U32 ms_elapsed); -	static void cleanupClass();		// Delete sLocal -	 +    LLLFSThread(bool threaded = true); +    ~LLLFSThread(); + +    // Return a Request handle +    handle_t read(const std::string& filename,  /* Flawfinder: ignore */ +                  U8* buffer, S32 offset, S32 numbytes, +                  Responder* responder); +    handle_t write(const std::string& filename, +                   U8* buffer, S32 offset, S32 numbytes, +                   Responder* responder); + +    // static initializers +    static void initClass(bool local_is_threaded = true); // Setup sLocal +    static S32 updateClass(U32 ms_elapsed); +    static void cleanupClass();     // Delete sLocal +  public: -	static LLLFSThread* sLocal;		// Default local file thread +    static LLLFSThread* sLocal;     // Default local file thread  };  //============================================================================ diff --git a/indra/llfilesystem/tests/lldir_test.cpp b/indra/llfilesystem/tests/lldir_test.cpp index 60265cade6..6e191ad096 100644 --- a/indra/llfilesystem/tests/lldir_test.cpp +++ b/indra/llfilesystem/tests/lldir_test.cpp @@ -6,21 +6,21 @@   * $LicenseInfo:firstyear=2008&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -190,228 +190,228 @@ struct LLDir_Dummy: public LLDir  namespace tut  { -	struct LLDirTest +    struct LLDirTest          {          };          typedef test_group<LLDirTest> LLDirTest_t;          typedef LLDirTest_t::object LLDirTest_object_t;          tut::LLDirTest_t tut_LLDirTest("LLDir"); -	template<> template<> -	void LLDirTest_object_t::test<1>() -		// getDirDelimiter -	{ -		ensure("getDirDelimiter", !gDirUtilp->getDirDelimiter().empty()); -	} - -	template<> template<> -	void LLDirTest_object_t::test<2>() -		// getBaseFileName -	{ -		std::string delim = gDirUtilp->getDirDelimiter(); -		std::string rawFile = "foo"; -		std::string rawFileExt = "foo.bAr"; -		std::string rawFileNullExt = "foo."; -		std::string rawExt = ".bAr"; -		std::string rawDot = "."; -		std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; -		std::string pathExt = pathNoExt + ".eXt"; -		std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; -		std::string dottedPathExt = dottedPathNoExt + ".eXt"; - -		// foo[.bAr] - -		ensure_equals("getBaseFileName/r-no-ext/no-strip-exten", -			      gDirUtilp->getBaseFileName(rawFile, false), -			      "foo"); - -		ensure_equals("getBaseFileName/r-no-ext/strip-exten", -			      gDirUtilp->getBaseFileName(rawFile, true), -			      "foo"); - -		ensure_equals("getBaseFileName/r-ext/no-strip-exten", -			      gDirUtilp->getBaseFileName(rawFileExt, false), -			      "foo.bAr"); - -		ensure_equals("getBaseFileName/r-ext/strip-exten", -			      gDirUtilp->getBaseFileName(rawFileExt, true), -			      "foo"); - -		// foo. +    template<> template<> +    void LLDirTest_object_t::test<1>() +        // getDirDelimiter +    { +        ensure("getDirDelimiter", !gDirUtilp->getDirDelimiter().empty()); +    } + +    template<> template<> +    void LLDirTest_object_t::test<2>() +        // getBaseFileName +    { +        std::string delim = gDirUtilp->getDirDelimiter(); +        std::string rawFile = "foo"; +        std::string rawFileExt = "foo.bAr"; +        std::string rawFileNullExt = "foo."; +        std::string rawExt = ".bAr"; +        std::string rawDot = "."; +        std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; +        std::string pathExt = pathNoExt + ".eXt"; +        std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; +        std::string dottedPathExt = dottedPathNoExt + ".eXt"; + +        // foo[.bAr] + +        ensure_equals("getBaseFileName/r-no-ext/no-strip-exten", +                  gDirUtilp->getBaseFileName(rawFile, false), +                  "foo"); + +        ensure_equals("getBaseFileName/r-no-ext/strip-exten", +                  gDirUtilp->getBaseFileName(rawFile, true), +                  "foo"); + +        ensure_equals("getBaseFileName/r-ext/no-strip-exten", +                  gDirUtilp->getBaseFileName(rawFileExt, false), +                  "foo.bAr"); + +        ensure_equals("getBaseFileName/r-ext/strip-exten", +                  gDirUtilp->getBaseFileName(rawFileExt, true), +                  "foo"); + +        // foo. + +        ensure_equals("getBaseFileName/rn-no-ext/no-strip-exten", +                  gDirUtilp->getBaseFileName(rawFileNullExt, false), +                  "foo."); + +        ensure_equals("getBaseFileName/rn-no-ext/strip-exten", +                  gDirUtilp->getBaseFileName(rawFileNullExt, true), +                  "foo"); + +        // .bAr +        // interesting case - with no basename, this IS the basename, not the extension. + +        ensure_equals("getBaseFileName/e-ext/no-strip-exten", +                  gDirUtilp->getBaseFileName(rawExt, false), +                  ".bAr"); + +        ensure_equals("getBaseFileName/e-ext/strip-exten", +                  gDirUtilp->getBaseFileName(rawExt, true), +                  ".bAr"); + +        // . + +        ensure_equals("getBaseFileName/d/no-strip-exten", +                  gDirUtilp->getBaseFileName(rawDot, false), +                  "."); -		ensure_equals("getBaseFileName/rn-no-ext/no-strip-exten", -			      gDirUtilp->getBaseFileName(rawFileNullExt, false), -			      "foo."); +        ensure_equals("getBaseFileName/d/strip-exten", +                  gDirUtilp->getBaseFileName(rawDot, true), +                  "."); -		ensure_equals("getBaseFileName/rn-no-ext/strip-exten", -			      gDirUtilp->getBaseFileName(rawFileNullExt, true), -			      "foo"); - -		// .bAr -		// interesting case - with no basename, this IS the basename, not the extension. - -		ensure_equals("getBaseFileName/e-ext/no-strip-exten", -			      gDirUtilp->getBaseFileName(rawExt, false), -			      ".bAr"); - -		ensure_equals("getBaseFileName/e-ext/strip-exten", -			      gDirUtilp->getBaseFileName(rawExt, true), -			      ".bAr"); - -		// . - -		ensure_equals("getBaseFileName/d/no-strip-exten", -			      gDirUtilp->getBaseFileName(rawDot, false), -			      "."); - -		ensure_equals("getBaseFileName/d/strip-exten", -			      gDirUtilp->getBaseFileName(rawDot, true), -			      "."); - -		// aa/bb/cc/dd/ee[.eXt] - -		ensure_equals("getBaseFileName/no-ext/no-strip-exten", -			      gDirUtilp->getBaseFileName(pathNoExt, false), -			      "ee"); - -		ensure_equals("getBaseFileName/no-ext/strip-exten", -			      gDirUtilp->getBaseFileName(pathNoExt, true), -			      "ee"); - -		ensure_equals("getBaseFileName/ext/no-strip-exten", -			      gDirUtilp->getBaseFileName(pathExt, false), -			      "ee.eXt"); - -		ensure_equals("getBaseFileName/ext/strip-exten", -			      gDirUtilp->getBaseFileName(pathExt, true), -			      "ee"); - -		// aa/bb/cc.dd/ee[.eXt] - -		ensure_equals("getBaseFileName/d-no-ext/no-strip-exten", -			      gDirUtilp->getBaseFileName(dottedPathNoExt, false), -			      "ee"); - -		ensure_equals("getBaseFileName/d-no-ext/strip-exten", -			      gDirUtilp->getBaseFileName(dottedPathNoExt, true), -			      "ee"); - -		ensure_equals("getBaseFileName/d-ext/no-strip-exten", -			      gDirUtilp->getBaseFileName(dottedPathExt, false), -			      "ee.eXt"); - -		ensure_equals("getBaseFileName/d-ext/strip-exten", -			      gDirUtilp->getBaseFileName(dottedPathExt, true), -			      "ee"); -	} - -	template<> template<> -	void LLDirTest_object_t::test<3>() -		// getDirName -	{ -		std::string delim = gDirUtilp->getDirDelimiter(); -		std::string rawFile = "foo"; -		std::string rawFileExt = "foo.bAr"; -		std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; -		std::string pathExt = pathNoExt + ".eXt"; -		std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; -		std::string dottedPathExt = dottedPathNoExt + ".eXt"; +        // aa/bb/cc/dd/ee[.eXt] -		// foo[.bAr] +        ensure_equals("getBaseFileName/no-ext/no-strip-exten", +                  gDirUtilp->getBaseFileName(pathNoExt, false), +                  "ee"); -		ensure_equals("getDirName/r-no-ext", -			      gDirUtilp->getDirName(rawFile), -			      ""); +        ensure_equals("getBaseFileName/no-ext/strip-exten", +                  gDirUtilp->getBaseFileName(pathNoExt, true), +                  "ee"); -		ensure_equals("getDirName/r-ext", -			      gDirUtilp->getDirName(rawFileExt), -			      ""); +        ensure_equals("getBaseFileName/ext/no-strip-exten", +                  gDirUtilp->getBaseFileName(pathExt, false), +                  "ee.eXt"); -		// aa/bb/cc/dd/ee[.eXt] +        ensure_equals("getBaseFileName/ext/strip-exten", +                  gDirUtilp->getBaseFileName(pathExt, true), +                  "ee"); -		ensure_equals("getDirName/no-ext", -			      gDirUtilp->getDirName(pathNoExt), -			      "aa" + delim + "bb" + delim + "cc" + delim + "dd"); +        // aa/bb/cc.dd/ee[.eXt] -		ensure_equals("getDirName/ext", -			      gDirUtilp->getDirName(pathExt), -			      "aa" + delim + "bb" + delim + "cc" + delim + "dd"); +        ensure_equals("getBaseFileName/d-no-ext/no-strip-exten", +                  gDirUtilp->getBaseFileName(dottedPathNoExt, false), +                  "ee"); -		// aa/bb/cc.dd/ee[.eXt] +        ensure_equals("getBaseFileName/d-no-ext/strip-exten", +                  gDirUtilp->getBaseFileName(dottedPathNoExt, true), +                  "ee"); -		ensure_equals("getDirName/d-no-ext", -			      gDirUtilp->getDirName(dottedPathNoExt), -			      "aa" + delim + "bb" + delim + "cc.dd"); +        ensure_equals("getBaseFileName/d-ext/no-strip-exten", +                  gDirUtilp->getBaseFileName(dottedPathExt, false), +                  "ee.eXt"); -		ensure_equals("getDirName/d-ext", -			      gDirUtilp->getDirName(dottedPathExt), -			      "aa" + delim + "bb" + delim + "cc.dd"); -	} +        ensure_equals("getBaseFileName/d-ext/strip-exten", +                  gDirUtilp->getBaseFileName(dottedPathExt, true), +                  "ee"); +    } + +    template<> template<> +    void LLDirTest_object_t::test<3>() +        // getDirName +    { +        std::string delim = gDirUtilp->getDirDelimiter(); +        std::string rawFile = "foo"; +        std::string rawFileExt = "foo.bAr"; +        std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; +        std::string pathExt = pathNoExt + ".eXt"; +        std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; +        std::string dottedPathExt = dottedPathNoExt + ".eXt"; + +        // foo[.bAr] + +        ensure_equals("getDirName/r-no-ext", +                  gDirUtilp->getDirName(rawFile), +                  ""); -	template<> template<> -	void LLDirTest_object_t::test<4>() -		// getExtension -	{ -		std::string delim = gDirUtilp->getDirDelimiter(); -		std::string rawFile = "foo"; -		std::string rawFileExt = "foo.bAr"; -		std::string rawFileNullExt = "foo."; -		std::string rawExt = ".bAr"; -		std::string rawDot = "."; -		std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; -		std::string pathExt = pathNoExt + ".eXt"; -		std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; -		std::string dottedPathExt = dottedPathNoExt + ".eXt"; +        ensure_equals("getDirName/r-ext", +                  gDirUtilp->getDirName(rawFileExt), +                  ""); -		// foo[.bAr] +        // aa/bb/cc/dd/ee[.eXt] -		ensure_equals("getExtension/r-no-ext", -			      gDirUtilp->getExtension(rawFile), -			      ""); +        ensure_equals("getDirName/no-ext", +                  gDirUtilp->getDirName(pathNoExt), +                  "aa" + delim + "bb" + delim + "cc" + delim + "dd"); -		ensure_equals("getExtension/r-ext", -			      gDirUtilp->getExtension(rawFileExt), -			      "bar"); +        ensure_equals("getDirName/ext", +                  gDirUtilp->getDirName(pathExt), +                  "aa" + delim + "bb" + delim + "cc" + delim + "dd"); -		// foo. +        // aa/bb/cc.dd/ee[.eXt] + +        ensure_equals("getDirName/d-no-ext", +                  gDirUtilp->getDirName(dottedPathNoExt), +                  "aa" + delim + "bb" + delim + "cc.dd"); + +        ensure_equals("getDirName/d-ext", +                  gDirUtilp->getDirName(dottedPathExt), +                  "aa" + delim + "bb" + delim + "cc.dd"); +    } + +    template<> template<> +    void LLDirTest_object_t::test<4>() +        // getExtension +    { +        std::string delim = gDirUtilp->getDirDelimiter(); +        std::string rawFile = "foo"; +        std::string rawFileExt = "foo.bAr"; +        std::string rawFileNullExt = "foo."; +        std::string rawExt = ".bAr"; +        std::string rawDot = "."; +        std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee"; +        std::string pathExt = pathNoExt + ".eXt"; +        std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee"; +        std::string dottedPathExt = dottedPathNoExt + ".eXt"; -		ensure_equals("getExtension/rn-no-ext", -			      gDirUtilp->getExtension(rawFileNullExt), -			      ""); +        // foo[.bAr] -		// .bAr -		// interesting case - with no basename, this IS the basename, not the extension. +        ensure_equals("getExtension/r-no-ext", +                  gDirUtilp->getExtension(rawFile), +                  ""); -		ensure_equals("getExtension/e-ext", -			      gDirUtilp->getExtension(rawExt), -			      ""); +        ensure_equals("getExtension/r-ext", +                  gDirUtilp->getExtension(rawFileExt), +                  "bar"); -		// . +        // foo. -		ensure_equals("getExtension/d", -			      gDirUtilp->getExtension(rawDot), -			      ""); +        ensure_equals("getExtension/rn-no-ext", +                  gDirUtilp->getExtension(rawFileNullExt), +                  ""); -		// aa/bb/cc/dd/ee[.eXt] - -		ensure_equals("getExtension/no-ext", -			      gDirUtilp->getExtension(pathNoExt), -			      ""); - -		ensure_equals("getExtension/ext", -			      gDirUtilp->getExtension(pathExt), -			      "ext"); - -		// aa/bb/cc.dd/ee[.eXt] +        // .bAr +        // interesting case - with no basename, this IS the basename, not the extension. -		ensure_equals("getExtension/d-no-ext", -			      gDirUtilp->getExtension(dottedPathNoExt), -			      ""); +        ensure_equals("getExtension/e-ext", +                  gDirUtilp->getExtension(rawExt), +                  ""); -		ensure_equals("getExtension/d-ext", -			      gDirUtilp->getExtension(dottedPathExt), -			      "ext"); -	} +        // . + +        ensure_equals("getExtension/d", +                  gDirUtilp->getExtension(rawDot), +                  ""); + +        // aa/bb/cc/dd/ee[.eXt] + +        ensure_equals("getExtension/no-ext", +                  gDirUtilp->getExtension(pathNoExt), +                  ""); + +        ensure_equals("getExtension/ext", +                  gDirUtilp->getExtension(pathExt), +                  "ext"); + +        // aa/bb/cc.dd/ee[.eXt] + +        ensure_equals("getExtension/d-no-ext", +                  gDirUtilp->getExtension(dottedPathNoExt), +                  ""); + +        ensure_equals("getExtension/d-ext", +                  gDirUtilp->getExtension(dottedPathExt), +                  "ext"); +    }     std::string makeTestFile( const std::string& dir, const std::string& file )     { @@ -431,7 +431,7 @@ namespace tut        std::string uniqueDir;        bool foundUnused;        std::string delim = gDirUtilp->getDirDelimiter(); -       +        for (counter=0, foundUnused=false; !foundUnused; counter++ )        {           char counterStr[3]; @@ -440,7 +440,7 @@ namespace tut           foundUnused = ! ( LLFile::isdir(uniqueDir) || LLFile::isfile(uniqueDir) );        }        ensure("test directory '" + uniqueDir + "' creation failed", !LLFile::mkdir(uniqueDir)); -       +        return uniqueDir + delim; // HACK - apparently, the trailing delimiter is needed...     } @@ -487,7 +487,7 @@ namespace tut           }        }     } -    +     template<> template<>     void LLDirTest_object_t::test<5>()        // LLDirIterator::next diff --git a/indra/llfilesystem/tests/lldiriterator_test.cpp b/indra/llfilesystem/tests/lldiriterator_test.cpp index a65e3dada5..dc573b5555 100644 --- a/indra/llfilesystem/tests/lldiriterator_test.cpp +++ b/indra/llfilesystem/tests/lldiriterator_test.cpp @@ -6,21 +6,21 @@   * $LicenseInfo:firstyear=2011&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2011, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only., - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -32,7 +32,7 @@  namespace tut  { -     +      struct LLDirIteratorFixture      {          LLDirIteratorFixture() @@ -45,19 +45,19 @@ namespace tut      /*      CHOP-662 was originally introduced to deal with crashes deleting files from -    a directory (VWR-25500). However, this introduced a crash looking for  +    a directory (VWR-25500). However, this introduced a crash looking for      old chat logs as the glob_to_regex function in lldiriterator wasn't escaping lots of regexp characters      */      void test_chop_662(void)      { -        //  Check a selection of bad group names from the crash reports  +        //  Check a selection of bad group names from the crash reports          LLDirIterator iter(".","+bad-group-name]+?\?-??.*");          LLDirIterator iter1(".","))--@---bad-group-name2((?\?-??.*\\.txt"); -        LLDirIterator iter2(".","__^v--x)Cuide d sua vida(x--v^__?\?-??.*");  +        LLDirIterator iter2(".","__^v--x)Cuide d sua vida(x--v^__?\?-??.*");      }      template<> template<> -	void LLDirIteratorTest_t::test<1>() +    void LLDirIteratorTest_t::test<1>()      {         test_chop_662();      } | 
