summaryrefslogtreecommitdiff
path: root/indra/llvfs
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llvfs')
-rw-r--r--indra/llvfs/CMakeLists.txt83
-rw-r--r--indra/llvfs/lldir.cpp376
-rw-r--r--indra/llvfs/lldir.h131
-rw-r--r--indra/llvfs/lldir_linux.cpp105
-rw-r--r--indra/llvfs/lldir_linux.h43
-rw-r--r--indra/llvfs/lldir_mac.cpp102
-rw-r--r--indra/llvfs/lldir_mac.h43
-rw-r--r--indra/llvfs/lldir_solaris.cpp125
-rw-r--r--indra/llvfs/lldir_solaris.h40
-rw-r--r--indra/llvfs/lldir_win32.cpp126
-rw-r--r--indra/llvfs/lldir_win32.h43
-rw-r--r--indra/llvfs/lldirguard.h72
-rw-r--r--indra/llvfs/lllfsthread.cpp69
-rw-r--r--indra/llvfs/lllfsthread.h47
-rw-r--r--indra/llvfs/llpidlock.cpp276
-rw-r--r--indra/llvfs/llpidlock.h59
-rw-r--r--indra/llvfs/llvfile.cpp42
-rw-r--r--indra/llvfs/llvfile.h36
-rw-r--r--indra/llvfs/llvfs.cpp389
-rw-r--r--indra/llvfs/llvfs.h63
-rw-r--r--indra/llvfs/llvfsthread.cpp36
-rw-r--r--indra/llvfs/llvfsthread.h41
-rw-r--r--indra/llvfs/tests/lldir_test.cpp260
23 files changed, 1833 insertions, 774 deletions
diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
new file mode 100644
index 0000000000..722f4e2bfd
--- /dev/null
+++ b/indra/llvfs/CMakeLists.txt
@@ -0,0 +1,83 @@
+# -*- cmake -*-
+
+project(llvfs)
+
+include(00-Common)
+include(LLCommon)
+include(UnixInstall)
+
+include_directories(
+ ${LLCOMMON_INCLUDE_DIRS}
+ )
+
+set(llvfs_SOURCE_FILES
+ lldir.cpp
+ lllfsthread.cpp
+ llpidlock.cpp
+ llvfile.cpp
+ llvfs.cpp
+ llvfsthread.cpp
+ )
+
+set(llvfs_HEADER_FILES
+ CMakeLists.txt
+
+ lldir.h
+ lldirguard.h
+ lllfsthread.h
+ llpidlock.h
+ llvfile.h
+ llvfs.h
+ llvfsthread.h
+ )
+
+if (DARWIN)
+ LIST(APPEND llvfs_SOURCE_FILES lldir_mac.cpp)
+ LIST(APPEND llvfs_HEADER_FILES lldir_mac.h)
+endif (DARWIN)
+
+if (LINUX)
+ LIST(APPEND llvfs_SOURCE_FILES lldir_linux.cpp)
+ LIST(APPEND llvfs_HEADER_FILES lldir_linux.h)
+
+ if (VIEWER AND INSTALL)
+ set_source_files_properties(lldir_linux.cpp
+ PROPERTIES COMPILE_FLAGS
+ "-DAPP_RO_DATA_DIR=\\\"${APP_SHARE_DIR}\\\""
+ )
+ endif (VIEWER AND INSTALL)
+endif (LINUX)
+
+if (WINDOWS)
+ LIST(APPEND llvfs_SOURCE_FILES lldir_win32.cpp)
+ LIST(APPEND llvfs_HEADER_FILES lldir_win32.h)
+endif (WINDOWS)
+
+set_source_files_properties(${llvfs_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES})
+
+add_library (llvfs ${llvfs_SOURCE_FILES})
+
+if (DARWIN)
+ include(CMakeFindFrameworks)
+ find_library(CARBON_LIBRARY Carbon)
+ target_link_libraries(llvfs ${CARBON_LIBRARY})
+endif (DARWIN)
+
+
+if(LL_TESTS)
+ # Add tests
+ include(LLAddBuildTest)
+ # UNIT TESTS
+ SET(llvfs_TEST_SOURCE_FILES
+ # none so far
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llvfs "${llvfs_TEST_SOURCE_FILES}")
+
+ # INTEGRATION TESTS
+ set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+ # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
+ LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}")
+endif(LL_TESTS)
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index ae35b656d6..938fb008c9 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -2,30 +2,25 @@
* @file lldir.cpp
* @brief implementation of directory utilities base class
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
*/
@@ -40,7 +35,9 @@
#endif
#include "lldir.h"
+
#include "llerror.h"
+#include "lltimer.h" // ms_sleep()
#include "lluuid.h"
#if LL_WINDOWS
@@ -68,9 +65,10 @@ LLDir::LLDir()
mOSUserDir(""),
mOSUserAppDir(""),
mLindenUserDir(""),
+ mOSCacheDir(""),
mCAFile(""),
mTempDir(""),
- mDirDelimiter("")
+ mDirDelimiter("/") // fallback to forward slash if not overridden
{
}
@@ -87,20 +85,21 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
S32 result;
while (getNextFileInDir(dirname, mask, filename, FALSE))
{
- if ((filename == ".") || (filename == ".."))
+ fullpath = dirname;
+ fullpath += getDirDelimiter();
+ fullpath += filename;
+
+ if(LLFile::isdir(fullpath))
{
// skipping directory traversal filenames
count++;
continue;
}
- fullpath = dirname;
- fullpath += getDirDelimiter();
- fullpath += filename;
S32 retry_count = 0;
while (retry_count < 5)
{
- if (0 != LLFile::remove(fullpath.c_str()))
+ if (0 != LLFile::remove(fullpath))
{
result = errno;
llwarns << "Problem removing " << fullpath << " - errorcode: "
@@ -123,16 +122,20 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
}
const std::string LLDir::findFile(const std::string &filename,
- const std::string searchPath1,
- const std::string searchPath2,
- const std::string searchPath3)
+ 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);
+}
- std::vector<std::string>::iterator search_path_iter;
+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)
@@ -192,6 +195,11 @@ const std::string &LLDir::getOSUserAppDir() const
const std::string &LLDir::getLindenUserDir() const
{
+ if (mLindenUserDir.empty())
+ {
+ lldebugs << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << llendl;
+ }
+
return mLindenUserDir;
}
@@ -214,7 +222,26 @@ const std::string LLDir::getCacheDir(bool get_default) const
{
if (mCacheDir.empty() || get_default)
{
- std::string res;
+ 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";
@@ -223,14 +250,22 @@ const std::string LLDir::getCacheDir(bool get_default) const
{
res = getOSUserAppDir() + mDirDelimiter + "cache";
}
- return res;
}
else
{
- return mCacheDir;
+ res = getOSCacheDir() + mDirDelimiter + "SecondLife";
}
+ return res;
}
+
+
+const std::string &LLDir::getOSCacheDir() const
+{
+ return mOSCacheDir;
+}
+
+
const std::string &LLDir::getCAFile() const
{
return mCAFile;
@@ -246,12 +281,37 @@ const std::string &LLDir::getSkinDir() const
return mSkinDir;
}
+const std::string &LLDir::getUserSkinDir() const
+{
+ return mUserSkinDir;
+}
+
+const std::string& LLDir::getDefaultSkinDir() const
+{
+ return mDefaultSkinDir;
+}
+
+const std::string LLDir::getSkinBaseDir() const
+{
+ return mSkinBaseDir;
+}
+
+const std::string &LLDir::getLLPluginDir() const
+{
+ return mLLPluginDir;
+}
+
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const
{
return getExpandedFilename(location, "", filename);
}
-std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir, const std::string& in_filename) const
+std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir, const std::string& filename) const
+{
+ return getExpandedFilename(location, "", subdir, filename);
+}
+
+std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir1, const std::string& subdir2, const std::string& in_filename) const
{
std::string prefix;
switch (location)
@@ -265,25 +325,19 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
prefix += mDirDelimiter;
prefix += "app_settings";
break;
-
+
case LL_PATH_CHARACTER:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "character";
break;
- case LL_PATH_MOTIONS:
- prefix = getAppRODataDir();
- prefix += mDirDelimiter;
- prefix += "motions";
- break;
-
case LL_PATH_HELP:
prefix = "help";
break;
case LL_PATH_CACHE:
- prefix = getCacheDir();
+ prefix = getCacheDir();
break;
case LL_PATH_USER_SETTINGS:
@@ -294,6 +348,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
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.
+ return std::string();
+ }
break;
case LL_PATH_CHAT_LOGS:
@@ -318,24 +377,36 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
prefix = getSkinDir();
break;
- case LL_PATH_SKINS:
- prefix = getAppRODataDir();
+ case LL_PATH_DEFAULT_SKIN:
+ prefix = getDefaultSkinDir();
+ break;
+
+ case LL_PATH_USER_SKIN:
+ prefix = getOSUserAppDir();
+ prefix += mDirDelimiter;
+ prefix += "user_settings";
prefix += mDirDelimiter;
prefix += "skins";
break;
- case LL_PATH_HTML:
+ case LL_PATH_SKINS:
+ prefix = getSkinBaseDir();
+ break;
+
+ case LL_PATH_LOCAL_ASSETS:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
- prefix += "skins";
- prefix += mDirDelimiter;
- prefix += "html";
+ prefix += "local_assets";
break;
- case LL_PATH_MOZILLA_PROFILE:
- prefix = getOSUserAppDir();
+ case LL_PATH_EXECUTABLE:
+ prefix = getExecutableDir();
+ break;
+
+ case LL_PATH_FONTS:
+ prefix = getAppRODataDir();
prefix += mDirDelimiter;
- prefix += "browser_profile";
+ prefix += "fonts";
break;
default:
@@ -343,13 +414,19 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
}
std::string filename = in_filename;
- if (!subdir.empty())
+ if (!subdir2.empty())
{
- filename = subdir + mDirDelimiter + in_filename;
+ filename = subdir2 + mDirDelimiter + filename;
}
- else
+
+ if (!subdir1.empty())
{
- filename = in_filename;
+ filename = subdir1 + mDirDelimiter + filename;
+ }
+
+ if (prefix.empty())
+ {
+ llwarns << "prefix is empty, possible bad filename" << llendl;
}
std::string expanded_filename;
@@ -376,15 +453,77 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
expanded_filename.assign("");
}
- //llinfos << "*** EXPANDED FILENAME: <" << mExpandedFilename << ">" << llendl;
-
+ //llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl;
return expanded_filename;
}
+std::string LLDir::getBaseFileName(const std::string& filepath, bool strip_exten) const
+{
+ std::size_t offset = filepath.find_last_of(getDirDelimiter());
+ offset = (offset == std::string::npos) ? 0 : offset+1;
+ std::string res = filepath.substr(offset, std::string::npos);
+ if (strip_exten)
+ {
+ offset = res.find_last_of('.');
+ if (offset != std::string::npos &&
+ offset != 0) // if basename STARTS with '.', don't strip
+ {
+ res = res.substr(0, offset);
+ }
+ }
+ return res;
+}
+
+std::string LLDir::getDirName(const std::string& filepath) const
+{
+ std::size_t offset = filepath.find_last_of(getDirDelimiter());
+ S32 len = (offset == std::string::npos) ? 0 : offset;
+ std::string dirname = filepath.substr(0, len);
+ return dirname;
+}
+
+std::string LLDir::getExtension(const std::string& filepath) const
+{
+ if (filepath.empty())
+ return std::string();
+ std::string basename = getBaseFileName(filepath, false);
+ std::size_t offset = basename.find_last_of('.');
+ std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1);
+ LLStringUtil::toLower(exten);
+ return exten;
+}
+
+std::string LLDir::findSkinnedFilename(const std::string &filename) const
+{
+ return findSkinnedFilename("", "", filename);
+}
+
+std::string LLDir::findSkinnedFilename(const std::string &subdir, const std::string &filename) const
+{
+ return findSkinnedFilename("", subdir, filename);
+}
+
+std::string LLDir::findSkinnedFilename(const std::string &subdir1, const std::string &subdir2, const std::string &filename) const
+{
+ // generate subdirectory path fragment, e.g. "/foo/bar", "/foo", ""
+ std::string subdirs = ((subdir1.empty() ? "" : mDirDelimiter) + subdir1)
+ + ((subdir2.empty() ? "" : mDirDelimiter) + subdir2);
+
+ std::vector<std::string> search_paths;
+
+ search_paths.push_back(getUserSkinDir() + subdirs); // first look in user skin override
+ search_paths.push_back(getSkinDir() + subdirs); // then in current skin
+ search_paths.push_back(getDefaultSkinDir() + subdirs); // then default skin
+ search_paths.push_back(getCacheDir() + subdirs); // and last in preload directory
+
+ std::string found_file = findFile(filename, search_paths);
+ return found_file;
+}
+
std::string LLDir::getTempFilename() const
{
LLUUID random_uuid;
- char uuid_str[64]; /* Flawfinder: ignore */
+ std::string uuid_str;
random_uuid.generate();
random_uuid.toString(uuid_str);
@@ -397,26 +536,46 @@ std::string LLDir::getTempFilename() const
return temp_filename;
}
-void LLDir::setLindenUserDir(const std::string &first, const std::string &last)
+// static
+std::string LLDir::getScrubbedFileName(const std::string uncleanFileName)
{
- // if both first and last aren't set, assume we're grabbing the cached dir
- if (!first.empty() && !last.empty())
+ std::string name(uncleanFileName);
+ const std::string illegalChars(getForbiddenFileChars());
+ // replace any illegal file chars with and underscore '_'
+ for( unsigned int i = 0; i < illegalChars.length(); i++ )
+ {
+ int j = -1;
+ while((j = name.find(illegalChars[i])) > -1)
+ {
+ name[j] = '_';
+ }
+ }
+ return name;
+}
+
+// static
+std::string LLDir::getForbiddenFileChars()
+{
+ return "\\/:*?\"<>|";
+}
+
+void LLDir::setLindenUserDir(const std::string &username)
+{
+ // if the username isn't set, that's bad
+ if (!username.empty())
{
// some platforms have case-sensitive filesystems, so be
// utterly consistent with our firstname/lastname case.
- LLString firstlower(first);
- LLString::toLower(firstlower);
- LLString lastlower(last);
- LLString::toLower(lastlower);
+ std::string userlower(username);
+ LLStringUtil::toLower(userlower);
+ LLStringUtil::replaceChar(userlower, ' ', '_');
mLindenUserDir = getOSUserAppDir();
mLindenUserDir += mDirDelimiter;
- mLindenUserDir += firstlower.c_str();
- mLindenUserDir += "_";
- mLindenUserDir += lastlower.c_str();
+ mLindenUserDir += userlower;
}
else
{
- llerrs << "Invalid name for LLDir::setLindenUserDir" << llendl;
+ llerrs << "NULL name for LLDir::setLindenUserDir" << llendl;
}
dumpCurrentDirectories();
@@ -434,36 +593,46 @@ void LLDir::setChatLogsDir(const std::string &path)
}
}
-void LLDir::setPerAccountChatLogsDir(const std::string &first, const std::string &last)
+void LLDir::setPerAccountChatLogsDir(const std::string &username)
{
// if both first and last aren't set, assume we're grabbing the cached dir
- if (!first.empty() && !last.empty())
+ if (!username.empty())
{
// some platforms have case-sensitive filesystems, so be
// utterly consistent with our firstname/lastname case.
- LLString firstlower(first);
- LLString::toLower(firstlower);
- LLString lastlower(last);
- LLString::toLower(lastlower);
+ std::string userlower(username);
+ LLStringUtil::toLower(userlower);
+ LLStringUtil::replaceChar(userlower, ' ', '_');
mPerAccountChatLogsDir = getChatLogsDir();
mPerAccountChatLogsDir += mDirDelimiter;
- mPerAccountChatLogsDir += firstlower.c_str();
- mPerAccountChatLogsDir += "_";
- mPerAccountChatLogsDir += lastlower.c_str();
+ mPerAccountChatLogsDir += userlower;
}
else
{
- llwarns << "Invalid name for LLDir::setPerAccountChatLogsDir" << llendl;
+ llerrs << "NULL name for LLDir::setPerAccountChatLogsDir" << llendl;
}
+
}
void LLDir::setSkinFolder(const std::string &skin_folder)
{
- mSkinDir = getAppRODataDir();
- mSkinDir += mDirDelimiter;
- mSkinDir += "skins";
+ mSkinDir = getSkinBaseDir();
mSkinDir += mDirDelimiter;
mSkinDir += skin_folder;
+
+ // user modifications to current skin
+ // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle
+ mUserSkinDir = getOSUserAppDir();
+ mUserSkinDir += mDirDelimiter;
+ mUserSkinDir += "skins";
+ mUserSkinDir += mDirDelimiter;
+ mUserSkinDir += skin_folder;
+
+ // base skin which is used as fallback for all skinned files
+ // e.g. c:\program files\secondlife\skins\default
+ mDefaultSkinDir = getSkinBaseDir();
+ mDefaultSkinDir += mDirDelimiter;
+ mDefaultSkinDir += "default";
}
bool LLDir::setCacheDir(const std::string &path)
@@ -476,13 +645,13 @@ bool LLDir::setCacheDir(const std::string &path)
}
else
{
- LLFile::mkdir(path.c_str());
+ LLFile::mkdir(path);
std::string tempname = path + mDirDelimiter + "temp";
- LLFILE* file = LLFile::fopen(tempname.c_str(),"wt");
+ LLFILE* file = LLFile::fopen(tempname,"wt");
if (file)
{
fclose(file);
- LLFile::remove(tempname.c_str());
+ LLFile::remove(tempname);
mCacheDir = path;
return true;
}
@@ -492,21 +661,22 @@ bool LLDir::setCacheDir(const std::string &path)
void LLDir::dumpCurrentDirectories()
{
- llinfos << "Current Directories:" << llendl;
-
- llinfos << " CurPath: " << getCurPath() << llendl;
- llinfos << " AppName: " << getAppName() << llendl;
- llinfos << " ExecutableFilename: " << getExecutableFilename() << llendl;
- llinfos << " ExecutableDir: " << getExecutableDir() << llendl;
- llinfos << " ExecutablePathAndName: " << getExecutablePathAndName() << llendl;
- llinfos << " WorkingDir: " << getWorkingDir() << llendl;
- llinfos << " AppRODataDir: " << getAppRODataDir() << llendl;
- llinfos << " OSUserDir: " << getOSUserDir() << llendl;
- llinfos << " OSUserAppDir: " << getOSUserAppDir() << llendl;
- llinfos << " LindenUserDir: " << getLindenUserDir() << llendl;
- llinfos << " TempDir: " << getTempDir() << llendl;
- llinfos << " CAFile: " << getCAFile() << llendl;
- llinfos << " SkinDir: " << getSkinDir() << llendl;
+ LL_DEBUGS2("AppInit","Directories") << "Current Directories:" << LL_ENDL;
+
+ LL_DEBUGS2("AppInit","Directories") << " CurPath: " << getCurPath() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " AppName: " << getAppName() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " ExecutableFilename: " << getExecutableFilename() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " ExecutableDir: " << getExecutableDir() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " ExecutablePathAndName: " << getExecutablePathAndName() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " WorkingDir: " << getWorkingDir() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " AppRODataDir: " << getAppRODataDir() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " OSUserDir: " << getOSUserDir() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " OSUserAppDir: " << getOSUserAppDir() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " TempDir: " << getTempDir() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " CAFile: " << getCAFile() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
}
@@ -515,15 +685,15 @@ 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.c_str(), 0700);
+ LLFile::mkdir(dir_name, 0700);
#else
struct stat dir_stat;
- if(0 != LLFile::stat(dir_name.c_str(), &dir_stat))
+ if(0 != LLFile::stat(dir_name, &dir_stat))
{
S32 stat_rv = errno;
if(ENOENT == stat_rv)
{
- if(0 != LLFile::mkdir(dir_name.c_str(), 0700)) // octal
+ if(0 != LLFile::mkdir(dir_name, 0700)) // octal
{
llerrs << "Unable to create directory: " << dir_name << llendl;
}
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index 4426935e5c..4f63c04aab 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -2,55 +2,58 @@
* @file lldir.h
* @brief Definition of directory utilities class
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLDIR_H
#define LL_LLDIR_H
+#if LL_SOLARIS
+#include <sys/param.h>
+#define MAX_PATH MAXPATHLEN
+#endif
+
+// these numbers *may* get serialized (really??), 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,
+ 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_MOTIONS = 6,
- LL_PATH_HELP = 7,
- LL_PATH_LOGS = 8,
- LL_PATH_TEMP = 9,
- LL_PATH_SKINS = 10,
- LL_PATH_TOP_SKIN = 11,
- LL_PATH_CHAT_LOGS = 12,
- LL_PATH_PER_ACCOUNT_CHAT_LOGS = 13,
- LL_PATH_MOZILLA_PROFILE = 14,
- LL_PATH_HTML = 15,
- LL_PATH_COUNT = 16
+ 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_LAST
} ELLPath;
@@ -60,18 +63,28 @@ class LLDir
LLDir();
virtual ~LLDir();
- virtual void initAppDirs(const std::string &app_name) = 0;
- public:
- virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
+ // 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);
// pure virtual functions
- virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0;
- virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) = 0;
- virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) = 0;
+ virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0;
+ virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) = 0;
+ virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) = 0;
virtual std::string getCurPath() = 0;
- virtual BOOL fileExists(const std::string &filename) = 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;
+
+ 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 findFile(const std::string &filename, const std::string searchPath1 = "", const std::string searchPath2 = "", const std::string searchPath3 = "");
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
@@ -85,25 +98,49 @@ class LLDir
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 &getSkinDir() const; // User-specified skin folder.
+ 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 &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default
+ 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
// Expanded filename
std::string getExpandedFilename(ELLPath location, const std::string &filename) const;
std::string getExpandedFilename(ELLPath location, const std::string &subdir, const std::string &filename) const;
+ std::string getExpandedFilename(ELLPath location, const std::string &subdir1, const std::string &subdir2, const std::string &filename) const;
+
+ // Base and Directory name extraction
+ std::string getBaseFileName(const std::string& filepath, bool strip_exten = false) const;
+ std::string getDirName(const std::string& filepath) const;
+ std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav"
+
+ // these methods search the various skin paths for the specified file in the following order:
+ // getUserSkinDir(), getSkinDir(), getDefaultSkinDir()
+ std::string findSkinnedFilename(const std::string &filename) const;
+ std::string findSkinnedFilename(const std::string &subdir, const std::string &filename) const;
+ std::string findSkinnedFilename(const std::string &subdir1, const std::string &subdir2, const std::string &filename) const;
// random filename in common temporary directory
std::string getTempFilename() const;
+ // For producing safe download file names from potentially unsafe ones
+ static std::string getScrubbedFileName(const std::string uncleanFileName);
+ static std::string getForbiddenFileChars();
+
virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir
- virtual void setPerAccountChatLogsDir(const std::string &first, const std::string &last); // Set the per user chat log directory.
- virtual void setLindenUserDir(const std::string &first, const std::string &last); // Set the linden user 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);
virtual bool setCacheDir(const std::string &path);
virtual void dumpCurrentDirectories();
+ // Utility routine
+ std::string buildSLOSCacheDir() const;
+
protected:
std::string mAppName; // install directory under progams/ ie "SecondLife"
std::string mExecutablePathAndName; // full path + Filename of .exe
@@ -118,9 +155,15 @@ protected:
std::string mChatLogsDir; // Location for chat logs.
std::string mCAFile; // Location of the TLS certificate authority PEM file.
std::string mTempDir;
- std::string mCacheDir;
+ 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 mSkinDir; // Location for u ser-specified skin info.
+ std::string mSkinBaseDir; // Base for skins paths.
+ std::string mSkinDir; // Location for current skin info.
+ std::string mDefaultSkinDir; // Location for default skin info.
+ std::string mUserSkinDir; // Location for user-modified skin info.
+ std::string mLLPluginDir; // Location for plugins and plugin shell
};
void dir_exists_or_crash(const std::string &dir_name);
diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp
index 8f9f577804..a1c6669b97 100644
--- a/indra/llvfs/lldir_linux.cpp
+++ b/indra/llvfs/lldir_linux.cpp
@@ -2,30 +2,25 @@
* @file lldir_linux.cpp
* @brief Implementation of directory utilities for linux
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -93,10 +88,28 @@ LLDir_Linux::LLDir_Linux()
mExecutablePathAndName = "";
mExecutableDir = tmp_str;
mWorkingDir = tmp_str;
+#ifdef APP_RO_DATA_DIR
+ mAppRODataDir = APP_RO_DATA_DIR;
+#else
mAppRODataDir = tmp_str;
+#endif
+ std::string::size_type indra_pos = mExecutableDir.find("/indra");
+ if (indra_pos != std::string::npos)
+ {
+ // ...we're in a dev checkout
+ mSkinBaseDir = mExecutableDir.substr(0, indra_pos) + "/indra/newview/skins";
+ llinfos << "Running in dev checkout with mSkinBaseDir "
+ << mSkinBaseDir << llendl;
+ }
+ else
+ {
+ // ...normal installation running
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ }
+
mOSUserDir = getCurrentUserHome(tmp_str);
mOSUserAppDir = "";
- mLindenUserDir = tmp_str;
+ mLindenUserDir = "";
char path [32]; /* Flawfinder: ignore */
@@ -123,6 +136,8 @@ LLDir_Linux::LLDir_Linux()
}
}
+ mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
+
// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
mTempDir = "/tmp";
}
@@ -134,12 +149,19 @@ LLDir_Linux::~LLDir_Linux()
// Implementation
-void LLDir_Linux::initAppDirs(const std::string &app_name)
+void LLDir_Linux::initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir)
{
+ // Allow override so test apps can read newview directory
+ if (!app_read_only_data_dir.empty())
+ {
+ mAppRODataDir = app_read_only_data_dir;
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ }
mAppName = app_name;
- LLString upper_app_name(app_name);
- LLString::toUpper(upper_app_name);
+ std::string upper_app_name(app_name);
+ LLStringUtil::toUpper(upper_app_name);
char* app_home_env = getenv((upper_app_name + "_USER_DIR").c_str()); /* Flawfinder: ignore */
if (app_home_env)
@@ -153,14 +175,14 @@ void LLDir_Linux::initAppDirs(const std::string &app_name)
mOSUserAppDir = mOSUserDir;
mOSUserAppDir += "/";
mOSUserAppDir += ".";
- LLString lower_app_name(app_name);
- LLString::toLower(lower_app_name);
+ 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.c_str());
+ int res = LLFile::mkdir(mOSUserAppDir);
if (res == -1)
{
if (errno != EEXIST)
@@ -171,7 +193,7 @@ void LLDir_Linux::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"").c_str());
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,""));
if (res == -1)
{
if (errno != EEXIST)
@@ -180,7 +202,7 @@ void LLDir_Linux::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"").c_str());
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,""));
if (res == -1)
{
if (errno != EEXIST)
@@ -189,7 +211,7 @@ void LLDir_Linux::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"").c_str());
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,""));
if (res == -1)
{
if (errno != EEXIST)
@@ -198,15 +220,6 @@ void LLDir_Linux::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"").c_str());
- if (res == -1)
- {
- if (errno != EEXIST)
- {
- llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
- }
- }
-
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
}
@@ -349,7 +362,7 @@ std::string LLDir_Linux::getCurPath()
}
-BOOL LLDir_Linux::fileExists(const std::string &filename)
+BOOL LLDir_Linux::fileExists(const std::string &filename) const
{
struct stat stat_data;
// Check the age of the file
@@ -365,3 +378,15 @@ BOOL LLDir_Linux::fileExists(const std::string &filename)
}
}
+
+/*virtual*/ std::string LLDir_Linux::getLLPluginLauncher()
+{
+ return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() +
+ "SLPlugin";
+}
+
+/*virtual*/ std::string LLDir_Linux::getLLPluginFilename(std::string base_name)
+{
+ return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() +
+ "lib" + base_name + ".so";
+}
diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h
index a81df89807..809959e873 100644
--- a/indra/llvfs/lldir_linux.h
+++ b/indra/llvfs/lldir_linux.h
@@ -2,30 +2,25 @@
* @file lldir_linux.h
* @brief Definition of directory utilities class for linux
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
*/
@@ -43,13 +38,17 @@ public:
LLDir_Linux();
virtual ~LLDir_Linux();
- virtual void initAppDirs(const std::string &app_name);
+ /*virtual*/ void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir);
public:
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
- /*virtual*/ BOOL fileExists(const std::string &filename);
+ /*virtual*/ BOOL fileExists(const std::string &filename) const;
+
+ /*virtual*/ std::string getLLPluginLauncher();
+ /*virtual*/ std::string getLLPluginFilename(std::string base_name);
private:
DIR *mDirp;
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index 3cf70d76c2..b41b0ec5dd 100644
--- a/indra/llvfs/lldir_mac.cpp
+++ b/indra/llvfs/lldir_mac.cpp
@@ -2,30 +2,25 @@
* @file lldir_mac.cpp
* @brief Implementation of directory utilities for Mac OS X
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
*/
@@ -67,7 +62,8 @@ static void CFStringRefToLLString(CFStringRef stringRef, std::string &llString,
{
if (stringRef)
{
- long bufferSize = CFStringGetLength(stringRef) + 1;
+ long stringSize = CFStringGetLength(stringRef) + 1;
+ long bufferSize = CFStringGetMaximumSizeForEncoding(stringSize,kCFStringEncodingUTF8);
char* buffer = new char[bufferSize];
memset(buffer, 0, bufferSize);
if (CFStringGetCString(stringRef, buffer, bufferSize, kCFStringEncodingUTF8))
@@ -141,9 +137,34 @@ LLDir_Mac::LLDir_Mac()
CFURLRefToLLString(executableParentURLRef, mExecutableDir, true);
// mAppRODataDir
- CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef);
+
+
+ // *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.
+
+ CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef);
CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true);
+ U32 indra_pos = mExecutableDir.find("/indra");
+ if (indra_pos != std::string::npos)
+ {
+ // ...we're in a dev checkout
+ mSkinBaseDir = mExecutableDir.substr(0, indra_pos)
+ + "/indra/newview/skins";
+ llinfos << "Running in dev checkout with mSkinBaseDir "
+ << mSkinBaseDir << llendl;
+ }
+ else
+ {
+ // ...normal installation running
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ }
+
// mOSUserDir
error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef);
if (error == noErr)
@@ -159,13 +180,22 @@ LLDir_Mac::LLDir_Mac()
// Create our sub-dirs
(void) CFCreateDirectory(&newFileRef, CFSTR("data"), NULL);
- (void) CFCreateDirectory(&newFileRef, CFSTR("cache"), NULL);
+ //(void) CFCreateDirectory(&newFileRef, CFSTR("cache"), NULL);
(void) CFCreateDirectory(&newFileRef, CFSTR("logs"), NULL);
(void) CFCreateDirectory(&newFileRef, CFSTR("user_settings"), NULL);
(void) CFCreateDirectory(&newFileRef, CFSTR("browser_profile"), NULL);
}
}
+ //mOSCacheDir
+ FSRef cacheDirRef;
+ error = FSFindFolder(kUserDomain, kCachedDataFolderType, true, &cacheDirRef);
+ if (error == noErr)
+ {
+ FSRefToLLString(&cacheDirRef, mOSCacheDir);
+ (void)CFCreateDirectory(&cacheDirRef, CFSTR("SecondLife"),NULL);
+ }
+
// mOSUserAppDir
mOSUserAppDir = mOSUserDir;
@@ -180,6 +210,8 @@ LLDir_Mac::LLDir_Mac()
}
mWorkingDir = getCurPath();
+
+ mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin";
CFRelease(executableURLRef);
executableURLRef = NULL;
@@ -193,8 +225,15 @@ LLDir_Mac::~LLDir_Mac()
// Implementation
-void LLDir_Mac::initAppDirs(const std::string &app_name)
+void LLDir_Mac::initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir)
{
+ // Allow override so test apps can read newview directory
+ if (!app_read_only_data_dir.empty())
+ {
+ mAppRODataDir = app_read_only_data_dir;
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ }
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
//dumpCurrentDirectories();
@@ -361,7 +400,7 @@ std::string LLDir_Mac::getCurPath()
-BOOL LLDir_Mac::fileExists(const std::string &filename)
+BOOL LLDir_Mac::fileExists(const std::string &filename) const
{
struct stat stat_data;
// Check the age of the file
@@ -378,4 +417,17 @@ BOOL LLDir_Mac::fileExists(const std::string &filename)
}
+/*virtual*/ std::string LLDir_Mac::getLLPluginLauncher()
+{
+ return gDirUtilp->getAppRODataDir() + gDirUtilp->getDirDelimiter() +
+ "SLPlugin.app/Contents/MacOS/SLPlugin";
+}
+
+/*virtual*/ std::string LLDir_Mac::getLLPluginFilename(std::string base_name)
+{
+ return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() +
+ base_name + ".dylib";
+}
+
+
#endif // LL_DARWIN
diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h
index c1244a2fa8..04c52dc940 100644
--- a/indra/llvfs/lldir_mac.h
+++ b/indra/llvfs/lldir_mac.h
@@ -2,30 +2,25 @@
* @file lldir_mac.h
* @brief Definition of directory utilities class for Mac OS X
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
*/
@@ -42,14 +37,18 @@ public:
LLDir_Mac();
virtual ~LLDir_Mac();
- virtual void initAppDirs(const std::string &app_name);
+ /*virtual*/ void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir);
public:
virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
virtual void getRandomFileInDir(const std::string &dirname, const std::string &ask, std::string &fname);
- virtual BOOL fileExists(const std::string &filename);
+ virtual BOOL fileExists(const std::string &filename) const;
+
+ /*virtual*/ std::string getLLPluginLauncher();
+ /*virtual*/ std::string getLLPluginFilename(std::string base_name);
private:
int mCurrentDirIndex;
diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp
index b13d3d05ea..4323dfd44a 100644
--- a/indra/llvfs/lldir_solaris.cpp
+++ b/indra/llvfs/lldir_solaris.cpp
@@ -2,30 +2,25 @@
* @file fmodwrapper.cpp
* @brief dummy source file for building a shared library to wrap libfmod.a
*
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- *
- * Copyright (c) 2005-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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,14 +31,13 @@
#include "llrand.h"
#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/param.h>
#include <unistd.h>
#include <glob.h>
#include <pwd.h>
#include <sys/utsname.h>
#define _STRUCTURED_PROC 1
#include <sys/procfs.h>
+#include <fcntl.h>
static std::string getCurrentUserHome(char* fallback)
{
@@ -82,7 +76,16 @@ LLDir_Solaris::LLDir_Solaris()
mDirp = NULL;
char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */
- getcwd(tmp_str, LL_MAX_PATH);
+ if (getcwd(tmp_str, LL_MAX_PATH) == NULL)
+ {
+ strcpy(tmp_str, "/tmp");
+ llwarns << "Could not get current directory; changing to "
+ << tmp_str << llendl;
+ if (chdir(tmp_str) == -1)
+ {
+ llerrs << "Could not change directory to " << tmp_str << llendl;
+ }
+ }
mExecutableFilename = "";
mExecutablePathAndName = "";
@@ -91,7 +94,7 @@ LLDir_Solaris::LLDir_Solaris()
mAppRODataDir = strdup(tmp_str);
mOSUserDir = getCurrentUserHome(tmp_str);
mOSUserAppDir = "";
- mLindenUserDir = tmp_str;
+ mLindenUserDir = "";
char path [LL_MAX_PATH]; /* Flawfinder: ignore */
@@ -121,22 +124,39 @@ LLDir_Solaris::LLDir_Solaris()
return;
}
+ char *p = execpath; // nuke trash in link, if any exists
+ int i = 0;
+ while(*p != NULL && ++i < LL_MAX_PATH && isprint((int)(*p++)));
+ *p = NULL;
+
mExecutablePathAndName = strdup(execpath);
llinfos << "mExecutablePathAndName = [" << mExecutablePathAndName << "]" << llendl;
+ //NOTE: Why force people to cd into the package directory?
+ // Look for SECONDLIFE env variable and use it, if set.
+
+ char *dcf = getenv("SECONDLIFE");
+ if(dcf != NULL){
+ (void)strcpy(path, dcf);
+ (void)strcat(path, "/bin"); //NOTE: make sure we point at the bin
+ mExecutableDir = strdup(path);
+ }else{
// plunk a null at last '/' to get exec dir
- char *s = execpath + strlen(execpath) -1;
- while(*s != '/' && s != execpath){
- --s;
- }
+ char *s = execpath + strlen(execpath) -1;
+ while(*s != '/' && s != execpath){
+ --s;
+ }
- if(s != execpath){
- *s = (char)NULL;
+ if(s != execpath){
+ *s = (char)NULL;
- mExecutableDir = strdup(execpath);
- llinfos << "mExecutableDir = [" << mExecutableDir << "]" << llendl;
+ mExecutableDir = strdup(execpath);
+ llinfos << "mExecutableDir = [" << mExecutableDir << "]" << llendl;
+ }
}
+ mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
+
// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
mTempDir = "/tmp";
}
@@ -148,12 +168,18 @@ LLDir_Solaris::~LLDir_Solaris()
// Implementation
-void LLDir_Solaris::initAppDirs(const std::string &app_name)
+void LLDir_Solaris::initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir)
{
+ // Allow override so test apps can read newview directory
+ if (!app_read_only_data_dir.empty())
+ {
+ mAppRODataDir = app_read_only_data_dir;
+ }
mAppName = app_name;
- LLString upper_app_name(app_name);
- LLString::toUpper(upper_app_name);
+ std::string upper_app_name(app_name);
+ LLStringUtil::toUpper(upper_app_name);
char* app_home_env = getenv((upper_app_name + "_USER_DIR").c_str()); /* Flawfinder: ignore */
if (app_home_env)
@@ -167,14 +193,14 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name)
mOSUserAppDir = mOSUserDir;
mOSUserAppDir += "/";
mOSUserAppDir += ".";
- LLString lower_app_name(app_name);
- LLString::toLower(lower_app_name);
+ 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.c_str());
+ int res = LLFile::mkdir(mOSUserAppDir);
if (res == -1)
{
if (errno != EEXIST)
@@ -185,7 +211,7 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"").c_str());
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,""));
if (res == -1)
{
if (errno != EEXIST)
@@ -194,7 +220,7 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"").c_str());
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,""));
if (res == -1)
{
if (errno != EEXIST)
@@ -203,7 +229,7 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"").c_str());
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,""));
if (res == -1)
{
if (errno != EEXIST)
@@ -212,15 +238,6 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"").c_str());
- if (res == -1)
- {
- if (errno != EEXIST)
- {
- llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
- }
- }
-
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
}
@@ -354,12 +371,16 @@ void LLDir_Solaris::getRandomFileInDir(const std::string &dirname, const std::st
std::string LLDir_Solaris::getCurPath()
{
char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */
- getcwd(tmp_str, LL_MAX_PATH);
+ if (getcwd(tmp_str, LL_MAX_PATH) == NULL)
+ {
+ llwarns << "Could not get current directory" << llendl;
+ tmp_str[0] = '\0';
+ }
return tmp_str;
}
-BOOL LLDir_Solaris::fileExists(const std::string &filename)
+BOOL LLDir_Solaris::fileExists(const std::string &filename) const
{
struct stat stat_data;
// Check the age of the file
diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h
index 34e7f71dac..6e0c5cfc69 100644
--- a/indra/llvfs/lldir_solaris.h
+++ b/indra/llvfs/lldir_solaris.h
@@ -2,30 +2,25 @@
* @file fmodwrapper.cpp
* @brief dummy source file for building a shared library to wrap libfmod.a
*
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- *
- * Copyright (c) 2005-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -43,13 +38,14 @@ public:
LLDir_Solaris();
virtual ~LLDir_Solaris();
- virtual void initAppDirs(const std::string &app_name);
+ /*virtual*/ void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir);
public:
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
- /*virtual*/ BOOL fileExists(const std::string &filename);
+ /*virtual*/ BOOL fileExists(const std::string &filename) const;
private:
DIR *mDirp;
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index f415fe56ed..52d864e26f 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -2,30 +2,25 @@
* @file lldir_win32.cpp
* @brief Implementation of directory utilities for windows
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
*/
@@ -58,14 +53,18 @@ LLDir_Win32::LLDir_Win32()
mOSUserDir = utf16str_to_utf8str(llutf16string(w_str));
- // Local Settings\Application Data is where cache files should
- // go, they don't get copied to the server if the user moves his
- // profile around on the network. JC
+ // We want cache files to go on the local disk, even if the
+ // user is on a network with a "roaming profile".
+ //
+ // On XP this is:
+ // C:\Docments and Settings\James\Local Settings\Application Data
+ // On Vista this is:
+ // C:\Users\James\AppData\Local
//
- // TODO: patch the installer to remove old cache files on update, then
- // enable this code.
- //SHGetSpecialFolderPath(NULL, w_str, CSIDL_LOCAL_APPDATA, TRUE);
- //mOSUserCacheDir = utf16str_to_utf8str(llutf16string(w_str));
+ // We used to store the cache in AppData\Roaming, and the installer
+ // cleans up that version on upgrade. JC
+ SHGetSpecialFolderPath(NULL, w_str, CSIDL_LOCAL_APPDATA, TRUE);
+ mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str));
if (GetTempPath(MAX_PATH, w_str))
{
@@ -116,10 +115,36 @@ LLDir_Win32::LLDir_Win32()
GetCurrentDirectory(MAX_PATH, w_str);
mExecutableDir = utf16str_to_utf8str(llutf16string(w_str));
#endif
- if (strstr(mExecutableDir.c_str(), "indra\\newview"))
- mAppRODataDir = getCurPath();
- else
- mAppRODataDir = mExecutableDir;
+
+ if (mExecutableDir.find("indra") == std::string::npos)
+ {
+ // Running from installed directory. Make sure current
+ // directory isn't something crazy (e.g. if invoking from
+ // command line).
+ SetCurrentDirectory(utf8str_to_utf16str(mExecutableDir).c_str());
+ GetCurrentDirectory(MAX_PATH, w_str);
+ mWorkingDir = utf16str_to_utf8str(llutf16string(w_str));
+ }
+ mAppRODataDir = mWorkingDir;
+
+ llinfos << "mAppRODataDir = " << mAppRODataDir << llendl;
+
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+
+ // Build the default cache directory
+ mDefaultCacheDir = buildSLOSCacheDir();
+
+ // Make sure it exists
+ int res = LLFile::mkdir(mDefaultCacheDir);
+ if (res == -1)
+ {
+ if (errno != EEXIST)
+ {
+ llwarns << "Couldn't create LL_PATH_CACHE dir " << mDefaultCacheDir << llendl;
+ }
+ }
+
+ mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
}
LLDir_Win32::~LLDir_Win32()
@@ -128,14 +153,21 @@ LLDir_Win32::~LLDir_Win32()
// Implementation
-void LLDir_Win32::initAppDirs(const std::string &app_name)
+void LLDir_Win32::initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir)
{
+ // Allow override so test apps can read newview directory
+ if (!app_read_only_data_dir.empty())
+ {
+ mAppRODataDir = app_read_only_data_dir;
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ }
mAppName = app_name;
mOSUserAppDir = mOSUserDir;
mOSUserAppDir += "\\";
mOSUserAppDir += app_name;
- int res = LLFile::mkdir(mOSUserAppDir.c_str());
+ int res = LLFile::mkdir(mOSUserAppDir);
if (res == -1)
{
if (errno != EEXIST)
@@ -147,7 +179,7 @@ void LLDir_Win32::initAppDirs(const std::string &app_name)
}
//dumpCurrentDirectories();
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"").c_str());
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,""));
if (res == -1)
{
if (errno != EEXIST)
@@ -156,7 +188,7 @@ void LLDir_Win32::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"").c_str());
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,""));
if (res == -1)
{
if (errno != EEXIST)
@@ -165,7 +197,7 @@ void LLDir_Win32::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"").c_str());
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,""));
if (res == -1)
{
if (errno != EEXIST)
@@ -174,15 +206,14 @@ void LLDir_Win32::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"").c_str());
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SKIN,""));
if (res == -1)
{
if (errno != EEXIST)
{
- llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
+ llwarns << "Couldn't create LL_PATH_SKINS dir " << getExpandedFilename(LL_PATH_USER_SKIN,"") << llendl;
}
}
-
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
}
@@ -338,12 +369,12 @@ std::string LLDir_Win32::getCurPath()
}
-BOOL LLDir_Win32::fileExists(const std::string &filename)
+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.c_str(), &stat_data);
+ int res = LLFile::stat(filename, &stat_data);
if (!res)
{
return TRUE;
@@ -355,6 +386,19 @@ BOOL LLDir_Win32::fileExists(const std::string &filename)
}
+/*virtual*/ std::string LLDir_Win32::getLLPluginLauncher()
+{
+ return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() +
+ "SLPlugin.exe";
+}
+
+/*virtual*/ std::string LLDir_Win32::getLLPluginFilename(std::string base_name)
+{
+ return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() +
+ base_name + ".dll";
+}
+
+
#if 0
// Utility function to get version number of a DLL
diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h
index bddf17503b..d3e45dc1f3 100644
--- a/indra/llvfs/lldir_win32.h
+++ b/indra/llvfs/lldir_win32.h
@@ -2,30 +2,25 @@
* @file lldir_win32.h
* @brief Definition of directory utilities class for windows
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
*/
@@ -40,13 +35,17 @@ public:
LLDir_Win32();
virtual ~LLDir_Win32();
- /*virtual*/ void initAppDirs(const std::string &app_name);
+ /*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 getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
/*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
- /*virtual*/ BOOL fileExists(const std::string &filename);
+ /*virtual*/ BOOL fileExists(const std::string &filename) const;
+
+ /*virtual*/ std::string getLLPluginLauncher();
+ /*virtual*/ std::string getLLPluginFilename(std::string base_name);
private:
BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
diff --git a/indra/llvfs/lldirguard.h b/indra/llvfs/lldirguard.h
new file mode 100644
index 0000000000..4330095ad0
--- /dev/null
+++ b/indra/llvfs/lldirguard.h
@@ -0,0 +1,72 @@
+/**
+ * @file lldirguard.h
+ * @brief Protect working directory from being changed in scope.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_DIRGUARD_H
+#define LL_DIRGUARD_H
+
+#include "linden_common.h"
+#include "llerror.h"
+
+#if LL_WINDOWS
+class LLDirectoryGuard
+{
+public:
+ LLDirectoryGuard()
+ {
+ mOrigDirLen = GetCurrentDirectory(MAX_PATH, mOrigDir);
+ }
+
+ ~LLDirectoryGuard()
+ {
+ mFinalDirLen = GetCurrentDirectory(MAX_PATH, mFinalDir);
+ if ((mOrigDirLen!=mFinalDirLen) ||
+ (wcsncmp(mOrigDir,mFinalDir,mOrigDirLen)!=0))
+ {
+ // Dir has changed
+ std::string mOrigDirUtf8 = utf16str_to_utf8str(llutf16string(mOrigDir));
+ std::string mFinalDirUtf8 = utf16str_to_utf8str(llutf16string(mFinalDir));
+ llinfos << "Resetting working dir from " << mFinalDirUtf8 << " to " << mOrigDirUtf8 << llendl;
+ SetCurrentDirectory(mOrigDir);
+ }
+ }
+
+private:
+ TCHAR mOrigDir[MAX_PATH];
+ DWORD mOrigDirLen;
+ TCHAR mFinalDir[MAX_PATH];
+ DWORD mFinalDirLen;
+};
+#else // No-op outside Windows.
+class LLDirectoryGuard
+{
+public:
+ LLDirectoryGuard() {}
+ ~LLDirectoryGuard() {}
+};
+#endif
+
+
+#endif
diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp
index 8d2dc72ffc..3d3ed9f6d4 100644
--- a/indra/llvfs/lllfsthread.cpp
+++ b/indra/llvfs/lllfsthread.cpp
@@ -2,35 +2,29 @@
* @file lllfsthread.cpp
* @brief LLLFSThread base class
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
-#include "llmath.h"
#include "lllfsthread.h"
#include "llstl.h"
#include "llapr.h"
@@ -73,6 +67,10 @@ LLLFSThread::LLLFSThread(bool threaded) :
LLQueuedThread("LFS", threaded),
mPriorityCounter(PRIORITY_LOWBITS)
{
+ if(!mLocalAPRFilePoolp)
+ {
+ mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
+ }
}
LLLFSThread::~LLLFSThread()
@@ -82,7 +80,7 @@ LLLFSThread::~LLLFSThread()
//----------------------------------------------------------------------------
-LLLFSThread::handle_t LLLFSThread::read(const LLString& filename, /* Flawfinder: ignore */
+LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfinder: ignore */
U8* buffer, S32 offset, S32 numbytes,
Responder* responder, U32 priority)
{
@@ -105,7 +103,7 @@ LLLFSThread::handle_t LLLFSThread::read(const LLString& filename, /* Flawfinder:
return handle;
}
-LLLFSThread::handle_t LLLFSThread::write(const LLString& filename,
+LLLFSThread::handle_t LLLFSThread::write(const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
Responder* responder, U32 priority)
{
@@ -131,7 +129,7 @@ LLLFSThread::handle_t LLLFSThread::write(const LLString& filename,
LLLFSThread::Request::Request(LLLFSThread* thread,
handle_t handle, U32 priority,
- operation_t op, const LLString& filename,
+ operation_t op, const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
Responder* responder) :
QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
@@ -184,8 +182,9 @@ bool LLLFSThread::Request::processRequest()
if (mOperation == FILE_READ)
{
llassert(mOffset >= 0);
- apr_file_t* filep = ll_apr_file_open(mFileName, LL_APR_RB, mThread->mAPRPoolp);
- if (!filep)
+ LLAPRFile infile ; // auto-closes
+ infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool());
+ if (!infile.getFileHandle())
{
llwarns << "LLLFS: Unable to read file: " << mFileName << llendl;
mBytesRead = 0; // fail
@@ -193,12 +192,11 @@ bool LLLFSThread::Request::processRequest()
}
S32 off;
if (mOffset < 0)
- off = ll_apr_file_seek(filep, APR_END, 0);
+ off = infile.seek(APR_END, 0);
else
- off = ll_apr_file_seek(filep, APR_SET, mOffset);
+ off = infile.seek(APR_SET, mOffset);
llassert_always(off >= 0);
- mBytesRead = ll_apr_file_read(filep, mBuffer, mBytes );
- apr_file_close(filep);
+ mBytesRead = infile.read(mBuffer, mBytes );
complete = true;
// llinfos << "LLLFSThread::READ:" << mFileName << " Bytes: " << mBytesRead << llendl;
}
@@ -207,8 +205,9 @@ bool LLLFSThread::Request::processRequest()
apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
if (mOffset < 0)
flags |= APR_APPEND;
- apr_file_t* filep = ll_apr_file_open(mFileName, flags, mThread->mAPRPoolp);
- if (!filep)
+ LLAPRFile outfile ; // auto-closes
+ outfile.open(mFileName, flags, mThread->getLocalAPRFilePool());
+ if (!outfile.getFileHandle())
{
llwarns << "LLLFS: Unable to write file: " << mFileName << llendl;
mBytesRead = 0; // fail
@@ -216,18 +215,16 @@ bool LLLFSThread::Request::processRequest()
}
if (mOffset >= 0)
{
- S32 seek = ll_apr_file_seek(filep, APR_SET, mOffset);
+ S32 seek = outfile.seek(APR_SET, mOffset);
if (seek < 0)
{
- apr_file_close(filep);
llwarns << "LLLFS: Unable to write file (seek failed): " << mFileName << llendl;
mBytesRead = 0; // fail
return true;
}
}
- mBytesRead = ll_apr_file_write(filep, mBuffer, mBytes );
+ mBytesRead = outfile.write(mBuffer, mBytes );
complete = true;
- apr_file_close(filep);
// llinfos << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << llendl;
}
else
diff --git a/indra/llvfs/lllfsthread.h b/indra/llvfs/lllfsthread.h
index 2a23f550e7..cdb5c75946 100644
--- a/indra/llvfs/lllfsthread.h
+++ b/indra/llvfs/lllfsthread.h
@@ -2,30 +2,25 @@
* @file lllfsthread.h
* @brief LLLFSThread base class
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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,7 +33,7 @@
#include <set>
#include "llapr.h"
-
+#include "llpointer.h"
#include "llqueuedthread.h"
//============================================================================
@@ -75,7 +70,7 @@ public:
public:
Request(LLLFSThread* thread,
handle_t handle, U32 priority,
- operation_t op, const LLString& filename,
+ operation_t op, const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
Responder* responder);
@@ -95,7 +90,7 @@ public:
{
return mBuffer;
}
- const LLString& getFilename()
+ const std::string& getFilename()
{
return mFileName;
}
@@ -108,7 +103,7 @@ public:
LLLFSThread* mThread;
operation_t mOperation;
- LLString mFileName;
+ std::string mFileName;
U8* mBuffer; // dest for reads, source for writes, new UUID for rename
S32 mOffset; // offset into file, -1 = append (WRITE only)
@@ -124,10 +119,10 @@ public:
~LLLFSThread();
// Return a Request handle
- handle_t read(const LLString& filename, /* Flawfinder: ignore */
+ handle_t read(const std::string& filename, /* Flawfinder: ignore */
U8* buffer, S32 offset, S32 numbytes,
Responder* responder, U32 pri=0);
- handle_t write(const LLString& filename,
+ handle_t write(const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
Responder* responder, U32 pri=0);
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
new file mode 100644
index 0000000000..0424f2379e
--- /dev/null
+++ b/indra/llvfs/llpidlock.cpp
@@ -0,0 +1,276 @@
+/**
+ * @file llformat.cpp
+ * @date January 2007
+ * @brief string formatting utility
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llpidlock.h"
+#include "lldir.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "llnametable.h"
+#include "llframetimer.h"
+
+#if LL_WINDOWS //For windows platform.
+
+#include <windows.h>
+
+namespace {
+ inline DWORD getpid() {
+ return GetCurrentProcessId();
+ }
+}
+
+bool isProcessAlive(U32 pid)
+{
+ return (bool) GetProcessVersion((DWORD)pid);
+}
+
+#else //Everyone Else
+bool isProcessAlive(U32 pid)
+{
+ return (bool) kill( (pid_t)pid, 0);
+}
+#endif //Everyone else.
+
+
+
+class LLPidLockFile
+{
+ public:
+ LLPidLockFile( ) :
+ mAutosave(false),
+ mSaving(false),
+ mWaiting(false),
+ mPID(getpid()),
+ mNameTable(NULL),
+ mClean(true)
+ {
+ mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
+ }
+ bool requestLock(LLNameTable<void *> *name_table, bool autosave,
+ bool force_immediate=FALSE, F32 timeout=300.0);
+ bool checkLock();
+ void releaseLock();
+
+ private:
+ void writeLockFile(LLSD pids);
+ public:
+ static LLPidLockFile& instance(); // return the singleton black list file
+
+ bool mAutosave;
+ bool mSaving;
+ bool mWaiting;
+ LLFrameTimer mTimer;
+ U32 mPID;
+ std::string mLockName;
+ std::string mSaveName;
+ LLSD mPIDS_sd;
+ LLNameTable<void*> *mNameTable;
+ bool mClean;
+};
+
+LLPidLockFile& LLPidLockFile::instance()
+{
+ static LLPidLockFile the_file;
+ return the_file;
+}
+
+void LLPidLockFile::writeLockFile(LLSD pids)
+{
+ llofstream ofile(mLockName);
+
+ if (!LLSDSerialize::toXML(pids,ofile))
+ {
+ llwarns << "Unable to write concurrent save lock file." << llendl;
+ }
+ ofile.close();
+}
+
+bool LLPidLockFile::requestLock(LLNameTable<void *> *name_table, bool autosave,
+ bool force_immediate, F32 timeout)
+{
+ bool readyToSave = FALSE;
+
+ if (mSaving) return FALSE; //Bail out if we're currently saving. Will not queue another save.
+
+ if (!mWaiting){
+ mNameTable=name_table;
+ mAutosave = autosave;
+ }
+
+ LLSD out_pids;
+ out_pids.append( (LLSD::Integer)mPID );
+
+ llifstream ifile(mLockName);
+
+ if (ifile.is_open())
+ { //If file exists, we need to decide whether or not to continue.
+ if ( force_immediate
+ || mTimer.hasExpired() ) //Only deserialize if we REALLY need to.
+ {
+
+ LLSD in_pids;
+
+ LLSDSerialize::fromXML(in_pids, ifile);
+
+ //Clean up any dead PIDS that might be in there.
+ for (LLSD::array_iterator i=in_pids.beginArray();
+ i !=in_pids.endArray();
+ ++i)
+ {
+ U32 stored_pid=(*i).asInteger();
+
+ if (isProcessAlive(stored_pid))
+ {
+ out_pids.append( (*i) );
+ }
+ }
+
+ readyToSave=TRUE;
+ }
+ ifile.close();
+ }
+ else
+ {
+ readyToSave=TRUE;
+ }
+
+ if (!mWaiting) //Not presently waiting to save. Queue up.
+ {
+ mTimer.resetWithExpiry(timeout);
+ mWaiting=TRUE;
+ }
+
+ if (readyToSave)
+ { //Potential race condition won't kill us. Ignore it.
+ writeLockFile(out_pids);
+ mSaving=TRUE;
+ }
+
+ return readyToSave;
+}
+
+bool LLPidLockFile::checkLock()
+{
+ return mWaiting;
+}
+
+void LLPidLockFile::releaseLock()
+{
+ llifstream ifile(mLockName);
+ LLSD in_pids;
+ LLSD out_pids;
+ bool write_file=FALSE;
+
+ LLSDSerialize::fromXML(in_pids, ifile);
+
+ //Clean up this PID and any dead ones.
+ for (LLSD::array_iterator i=in_pids.beginArray();
+ i !=in_pids.endArray();
+ ++i)
+ {
+ U32 stored_pid=(*i).asInteger();
+
+ if (stored_pid != mPID && isProcessAlive(stored_pid))
+ {
+ out_pids.append( (*i) );
+ write_file=TRUE;
+ }
+ }
+ ifile.close();
+
+ if (write_file)
+ {
+ writeLockFile(out_pids);
+ }
+ else
+ {
+ unlink(mLockName.c_str());
+ }
+
+ mSaving=FALSE;
+ mWaiting=FALSE;
+}
+
+//LLPidLock
+
+void LLPidLock::initClass() {
+ (void) LLPidLockFile::instance();
+}
+
+bool LLPidLock::checkLock()
+{
+ return LLPidLockFile::instance().checkLock();
+}
+
+bool LLPidLock::requestLock(LLNameTable<void *> *name_table, bool autosave,
+ bool force_immediate, F32 timeout)
+{
+ return LLPidLockFile::instance().requestLock(name_table,autosave,force_immediate,timeout);
+}
+
+void LLPidLock::releaseLock()
+{
+ return LLPidLockFile::instance().releaseLock();
+}
+
+bool LLPidLock::isClean()
+{
+ return LLPidLockFile::instance().mClean;
+}
+
+//getters
+LLNameTable<void *> * LLPidLock::getNameTable()
+{
+ return LLPidLockFile::instance().mNameTable;
+}
+
+bool LLPidLock::getAutosave()
+{
+ return LLPidLockFile::instance().mAutosave;
+}
+
+bool LLPidLock::getClean()
+{
+ return LLPidLockFile::instance().mClean;
+}
+
+std::string LLPidLock::getSaveName()
+{
+ return LLPidLockFile::instance().mSaveName;
+}
+
+//setters
+void LLPidLock::setClean(bool clean)
+{
+ LLPidLockFile::instance().mClean=clean;
+}
+
+void LLPidLock::setSaveName(std::string savename)
+{
+ LLPidLockFile::instance().mSaveName=savename;
+}
diff --git a/indra/llvfs/llpidlock.h b/indra/llvfs/llpidlock.h
new file mode 100644
index 0000000000..d3295f4911
--- /dev/null
+++ b/indra/llvfs/llpidlock.h
@@ -0,0 +1,59 @@
+/**
+ * @file llpidlock.h
+ * @brief System information debugging classes.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_PIDLOCK_H
+#define LL_PIDLOCK_H
+#include "llnametable.h"
+
+class LLSD;
+class LLFrameTimer;
+
+#if !LL_WINDOWS //For non-windows platforms.
+#include <signal.h>
+#endif
+
+namespace LLPidLock
+{
+ void initClass(); // { (void) LLPidLockFile::instance(); }
+
+ bool requestLock( LLNameTable<void *> *name_table=NULL, bool autosave=TRUE,
+ bool force_immediate=FALSE, F32 timeout=300.0);
+ bool checkLock();
+ void releaseLock();
+ bool isClean();
+
+ //getters
+ LLNameTable<void *> * getNameTable();
+ bool getAutosave();
+ bool getClean();
+ std::string getSaveName();
+
+ //setters
+ void setClean(bool clean);
+ void setSaveName(std::string savename);
+};
+
+#endif // LL_PIDLOCK_H
diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp
index bd4dfc2d78..a8db7b235e 100644
--- a/indra/llvfs/llvfile.cpp
+++ b/indra/llvfs/llvfile.cpp
@@ -2,30 +2,25 @@
* @file llvfile.cpp
* @brief Implementation of virtual file
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
*/
@@ -35,6 +30,7 @@
#include "llerror.h"
#include "llthread.h"
+#include "llstat.h"
#include "llvfs.h"
const S32 LLVFile::READ = 0x00000001;
@@ -42,6 +38,8 @@ const S32 LLVFile::WRITE = 0x00000002;
const S32 LLVFile::READ_WRITE = 0x00000003; // LLVFile::READ & LLVFile::WRITE
const S32 LLVFile::APPEND = 0x00000006; // 0x00000004 & LLVFile::WRITE
+static LLFastTimer::DeclareTimer FTM_VFILE_WAIT("VFile Wait");
+
//----------------------------------------------------------------------------
LLVFSThread* LLVFile::sVFSThread = NULL;
BOOL LLVFile::sAllocdVFSThread = FALSE;
@@ -316,7 +314,7 @@ BOOL LLVFile::setMaxSize(S32 size)
if (!mVFS->checkAvailable(size))
{
- LLFastTimer t(LLFastTimer::FTM_VFILE_WAIT);
+ LLFastTimer t(FTM_VFILE_WAIT);
S32 count = 0;
while (sVFSThread->getPending() > 1000)
{
@@ -424,7 +422,7 @@ bool LLVFile::isLocked(EVFSLock lock)
void LLVFile::waitForLock(EVFSLock lock)
{
- LLFastTimer t(LLFastTimer::FTM_VFILE_WAIT);
+ LLFastTimer t(FTM_VFILE_WAIT);
// spin until the lock clears
while (isLocked(lock))
{
diff --git a/indra/llvfs/llvfile.h b/indra/llvfs/llvfile.h
index cd4fc59174..7e9d9f73e5 100644
--- a/indra/llvfs/llvfile.h
+++ b/indra/llvfs/llvfile.h
@@ -2,30 +2,25 @@
* @file llvfile.h
* @brief Definition of virtual file
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -87,7 +82,6 @@ protected:
S32 mMode;
LLVFS *mVFS;
F32 mPriority;
- BOOL mOnReadQueue;
S32 mBytesRead;
LLVFSThread::handle_t mHandle;
diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp
index 417e48c07c..c1fe21c57d 100644
--- a/indra/llvfs/llvfs.cpp
+++ b/indra/llvfs/llvfs.cpp
@@ -2,30 +2,25 @@
* @file llvfs.cpp
* @brief Implementation of virtual file system
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
*/
@@ -45,7 +40,9 @@
#endif
#include "llvfs.h"
+
#include "llstl.h"
+#include "lltimer.h"
const S32 FILE_BLOCK_MASK = 0x000003FF; // 1024-byte blocks
const S32 VFS_CLEANUP_SIZE = 5242880; // how much space we free up in a single stroke
@@ -231,9 +228,11 @@ struct LLVFSFileBlock_less
const S32 LLVFSFileBlock::SERIAL_SIZE = 34;
-
-LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash)
-: mRemoveAfterCrash(remove_after_crash)
+
+LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash)
+: mRemoveAfterCrash(remove_after_crash),
+ mDataFP(NULL),
+ mIndexFP(NULL)
{
mDataMutex = new LLMutex(0);
@@ -244,29 +243,26 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
}
mValid = VFSVALID_OK;
mReadOnly = read_only;
- mIndexFilename = new char[strlen(index_filename) + 1]; /* Flawfinder: ignore */
- mDataFilename = new char[strlen(data_filename) + 1]; /* Flawfinder: ignore */
- if (mIndexFilename == NULL || mDataFilename == NULL)
- {
- llerrs << "Memory Allocation Failure" << llendl;
- return;
- }
- strcpy(mIndexFilename, index_filename); /* Flawfinder: ignore */
- strcpy(mDataFilename, data_filename); /* Flawfinder: ignore */
+ mIndexFilename = index_filename;
+ mDataFilename = data_filename;
const char *file_mode = mReadOnly ? "rb" : "r+b";
- if (! (mDataFP = openAndLock(mDataFilename, file_mode, mReadOnly)))
+ LL_INFOS("VFS") << "Attempting to open VFS index file " << mIndexFilename << LL_ENDL;
+ LL_INFOS("VFS") << "Attempting to open VFS data file " << mDataFilename << LL_ENDL;
+
+ mDataFP = openAndLock(mDataFilename, file_mode, mReadOnly);
+ if (!mDataFP)
{
-
if (mReadOnly)
{
- llwarns << "Can't find " << mDataFilename << " to open read-only VFS" << llendl;
+ LL_WARNS("VFS") << "Can't find " << mDataFilename << " to open read-only VFS" << LL_ENDL;
mValid = VFSVALID_BAD_CANNOT_OPEN_READONLY;
return;
}
-
- if((mDataFP = openAndLock(mDataFilename, "w+b", FALSE)))
+
+ mDataFP = openAndLock(mDataFilename, "w+b", FALSE);
+ if (mDataFP)
{
// Since we're creating this data file, assume any index file is bogus
// remove the index, since this vfs is now blank
@@ -274,56 +270,12 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
}
else
{
- llwarns << "Can't open VFS data file " << mDataFilename << " attempting to use alternate" << llendl;
-
- char *temp_index = new char[strlen(mIndexFilename) + 10]; /* Flawfinder: ignore */
- if (!temp_index)
- {
- llerrs << "Out of the memory in LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash)" << llendl;
- return;
- }
- char *temp_data = new char[strlen(mDataFilename) + 10]; /* Flawfinder: ignore */
- if (!temp_data)
- {
- llerrs << "Out of the memory in LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash)" << llendl;
- return;
- }
-
- for (U32 count = 0; count < 256; count++)
- {
- sprintf(temp_index, "%s.%u", mIndexFilename, count); /* Flawfinder: ignore */
- sprintf(temp_data, "%s.%u", mDataFilename, count); /* Flawfinder: ignore */
-
- // try just opening, then creating, each alternate
- if ((mDataFP = openAndLock(temp_data, "r+b", FALSE)))
- {
- break;
- }
-
- if ((mDataFP = openAndLock(temp_data, "w+b", FALSE)))
- {
- // we're creating the datafile, so nuke the indexfile
- LLFile::remove(temp_index);
- break;
- }
- }
-
- if (! mDataFP)
- {
- llwarns << "Couldn't open vfs data file after trying many alternates" << llendl;
- mValid = VFSVALID_BAD_CANNOT_CREATE;
- delete[] temp_index;
- delete[] temp_data;
- return;
- }
-
- delete[] mIndexFilename;
- delete[] mDataFilename;
-
- mIndexFilename = temp_index;
- mDataFilename = temp_data;
+ LL_WARNS("VFS") << "Couldn't open vfs data file "
+ << mDataFilename << LL_ENDL;
+ mValid = VFSVALID_BAD_CANNOT_CREATE;
+ return;
}
-
+
if (presize)
{
presizeDataFile(presize);
@@ -335,20 +287,14 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
if (!mReadOnly && mRemoveAfterCrash)
{
llstat marker_info;
- char* marker = new char[strlen(mDataFilename) + strlen(".open") + 1]; /* Flawfinder: ignore */
- if (!marker )
- {
- llerrs << "Out of memory in LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash)" << llendl;
- return;
- }
- sprintf(marker, "%s.open", mDataFilename); /* Flawfinder: ignore */
+ std::string marker = mDataFilename + ".open";
if (!LLFile::stat(marker, &marker_info))
{
// marker exists, kill the lock and the VFS files
unlockAndClose(mDataFP);
mDataFP = NULL;
- llwarns << "VFS: File left open on last run, removing old VFS file " << mDataFilename << llendl;
+ LL_WARNS("VFS") << "VFS: File left open on last run, removing old VFS file " << mDataFilename << LL_ENDL;
LLFile::remove(mIndexFilename);
LLFile::remove(mDataFilename);
LLFile::remove(marker);
@@ -356,7 +302,7 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
mDataFP = openAndLock(mDataFilename, "w+b", FALSE);
if (!mDataFP)
{
- llwarns << "Can't open VFS data file in crash recovery" << llendl;
+ LL_WARNS("VFS") << "Can't open VFS data file in crash recovery" << LL_ENDL;
mValid = VFSVALID_BAD_CANNOT_CREATE;
return;
}
@@ -366,8 +312,6 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
presizeDataFile(presize);
}
}
- delete [] marker;
- marker = NULL;
}
// determine the real file size
@@ -380,21 +324,20 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
llstat fbuf;
if (! LLFile::stat(mIndexFilename, &fbuf) &&
fbuf.st_size >= LLVFSFileBlock::SERIAL_SIZE &&
- (mIndexFP = openAndLock(mIndexFilename, file_mode, mReadOnly))
+ (mIndexFP = openAndLock(mIndexFilename, file_mode, mReadOnly)) // Yes, this is an assignment and not '=='
)
{
- U8 *buffer = new U8[fbuf.st_size];
- size_t nread = fread(buffer, 1, fbuf.st_size, mIndexFP);
-
- U8 *tmp_ptr = buffer;
-
+ std::vector<U8> buffer(fbuf.st_size);
+ size_t buf_offset = 0;
+ size_t nread = fread(&buffer[0], 1, fbuf.st_size, mIndexFP);
+
std::vector<LLVFSFileBlock*> files_by_loc;
- while (tmp_ptr < buffer + nread)
+ while (buf_offset < nread)
{
LLVFSFileBlock *block = new LLVFSFileBlock();
- block->deserialize(tmp_ptr, (S32)(tmp_ptr - buffer));
+ block->deserialize(&buffer[buf_offset], (S32)buf_offset);
// Do sanity check on this block.
// Note that this skips zero size blocks, which helps VFS
@@ -414,11 +357,10 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
if (block->mLength && block->mSize > 0)
{
// this is corrupt, not empty
- llwarns << "VFS corruption: " << block->mFileID << " (" << block->mFileType << ") at index " << block->mIndexLocation << " DS: " << data_size << llendl;
- llwarns << "Length: " << block->mLength << "\tLocation: " << block->mLocation << "\tSize: " << block->mSize << llendl;
- llwarns << "File has bad data - VFS removed" << llendl;
+ LL_WARNS("VFS") << "VFS corruption: " << block->mFileID << " (" << block->mFileType << ") at index " << block->mIndexLocation << " DS: " << data_size << LL_ENDL;
+ LL_WARNS("VFS") << "Length: " << block->mLength << "\tLocation: " << block->mLocation << "\tSize: " << block->mSize << LL_ENDL;
+ LL_WARNS("VFS") << "File has bad data - VFS removed" << LL_ENDL;
- delete[] buffer;
delete block;
unlockAndClose( mIndexFP );
@@ -429,21 +371,25 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
mDataFP = NULL;
LLFile::remove( mDataFilename );
+ LL_WARNS("VFS") << "Deleted corrupt VFS files "
+ << mDataFilename
+ << " and "
+ << mIndexFilename
+ << LL_ENDL;
+
mValid = VFSVALID_BAD_CORRUPT;
return;
}
else
{
// this is a null or bad entry, skip it
- S32 index_loc = (S32)(tmp_ptr - buffer);
- mIndexHoles.push_back(index_loc);
+ mIndexHoles.push_back(buf_offset);
delete block;
}
- tmp_ptr += LLVFSFileBlock::SERIAL_SIZE;
+ buf_offset += LLVFSFileBlock::SERIAL_SIZE;
}
- delete[] buffer;
std::sort(
files_by_loc.begin(),
@@ -481,13 +427,13 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
if (cur_file_block->mLocation == last_file_block->mLocation
&& cur_file_block->mLength == last_file_block->mLength)
{
- llwarns << "VFS: removing duplicate entry"
+ LL_WARNS("VFS") << "VFS: removing duplicate entry"
<< " at " << cur_file_block->mLocation
<< " length " << cur_file_block->mLength
<< " size " << cur_file_block->mSize
<< " ID " << cur_file_block->mFileID
<< " type " << cur_file_block->mFileType
- << llendl;
+ << LL_ENDL;
// Duplicate entries. Nuke them both for safety.
mFileBlocks.erase(*cur_file_block); // remove ID/type entry
@@ -528,12 +474,19 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
mDataFP = NULL;
LLFile::remove( mDataFilename );
- llwarns << "VFS: overlapping entries"
+ LL_WARNS("VFS") << "VFS: overlapping entries"
<< " at " << cur_file_block->mLocation
<< " length " << cur_file_block->mLength
<< " ID " << cur_file_block->mFileID
<< " type " << cur_file_block->mFileType
- << llendl;
+ << LL_ENDL;
+
+ LL_WARNS("VFS") << "Deleted corrupt VFS files "
+ << mDataFilename
+ << " and "
+ << mIndexFilename
+ << LL_ENDL;
+
mValid = VFSVALID_BAD_CORRUPT;
return;
}
@@ -559,11 +512,11 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
addFreeBlock(new LLVFSBlock(0, data_size));
}
}
- else
+ else // Pre-existing index file wasn't opened
{
if (mReadOnly)
{
- llwarns << "Can't find " << mIndexFilename << " to open read-only VFS" << llendl;
+ LL_WARNS("VFS") << "Can't find " << mIndexFilename << " to open read-only VFS" << LL_ENDL;
mValid = VFSVALID_BAD_CANNOT_OPEN_READONLY;
return;
}
@@ -572,7 +525,7 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
mIndexFP = openAndLock(mIndexFilename, "w+b", FALSE);
if (!mIndexFP)
{
- llwarns << "Couldn't open an index file for the VFS, probably a sharing violation!" << llendl;
+ LL_WARNS("VFS") << "Couldn't open an index file for the VFS, probably a sharing violation!" << LL_ENDL;
unlockAndClose( mDataFP );
mDataFP = NULL;
@@ -590,24 +543,17 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r
// Open marker file to look for bad shutdowns
if (!mReadOnly && mRemoveAfterCrash)
{
- char* marker = new char[strlen(mDataFilename) + strlen(".open") + 1];
- if (!marker)
- {
- llerrs << "Out of memory in LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash)" << llendl;
- return;
- }
- sprintf(marker, "%s.open", mDataFilename); /* Flawfinder: ignore */
- FILE* marker_fp = LLFile::fopen(marker, "w"); /* Flawfinder: ignore */
+ std::string marker = mDataFilename + ".open";
+ LLFILE* marker_fp = LLFile::fopen(marker, "w"); /* Flawfinder: ignore */
if (marker_fp)
{
fclose(marker_fp);
marker_fp = NULL;
}
- delete [] marker;
- marker = NULL;
}
- llinfos << "VFS: Using index file " << mIndexFilename << " and data file " << mDataFilename << llendl;
+ LL_INFOS("VFS") << "Using VFS index file " << mIndexFilename << LL_ENDL;
+ LL_INFOS("VFS") << "Using VFS data file " << mDataFilename << LL_ENDL;
mValid = VFSVALID_OK;
}
@@ -616,7 +562,7 @@ LLVFS::~LLVFS()
{
if (mDataMutex->isLocked())
{
- llerrs << "LLVFS destroyed with mutex locked" << llendl;
+ LL_ERRS("VFS") << "LLVFS destroyed with mutex locked" << LL_ENDL;
}
unlockAndClose(mIndexFP);
@@ -639,26 +585,54 @@ LLVFS::~LLVFS()
// Remove marker file
if (!mReadOnly && mRemoveAfterCrash)
{
- char* marker_file = new char[strlen(mDataFilename) + strlen(".open") + 1];
- if (marker_file == NULL)
- {
- llerrs << "Memory Allocation Failure" << llendl;
- return;
+ std::string marker = mDataFilename + ".open";
+ LLFile::remove(marker);
+ }
+
+ delete mDataMutex;
+}
+
+
+// Use this function normally to create LLVFS files.
+// Will append digits to the end of the filename with multiple re-trys
+// static
+LLVFS * LLVFS::createLLVFS(const std::string& index_filename,
+ const std::string& data_filename,
+ const BOOL read_only,
+ const U32 presize,
+ const BOOL remove_after_crash)
+{
+ LLVFS * new_vfs = new LLVFS(index_filename, data_filename, read_only, presize, remove_after_crash);
+
+ if( !new_vfs->isValid() )
+ { // First name failed, retry with new names
+ std::string retry_vfs_index_name;
+ std::string retry_vfs_data_name;
+ S32 count = 0;
+ while (!new_vfs->isValid() &&
+ count < 256)
+ { // Append '.<number>' to end of filenames
+ retry_vfs_index_name = index_filename + llformat(".%u",count);
+ retry_vfs_data_name = data_filename + llformat(".%u", count);
+
+ delete new_vfs; // Delete bad VFS and try again
+ new_vfs = new LLVFS(retry_vfs_index_name, retry_vfs_data_name, read_only, presize, remove_after_crash);
+
+ count++;
}
- sprintf(marker_file, "%s.open", mDataFilename); /* Flawfinder: ignore */
- LLFile::remove(marker_file);
- delete [] marker_file;
- marker_file = NULL;
}
- delete[] mIndexFilename;
- mIndexFilename = NULL;
- delete[] mDataFilename;
- mDataFilename = NULL;
+ if( !new_vfs->isValid() )
+ {
+ delete new_vfs; // Delete bad VFS
+ new_vfs = NULL; // Total failure
+ }
- delete mDataMutex;
+ return new_vfs;
}
+
+
void LLVFS::presizeDataFile(const U32 size)
{
if (!mDataFP)
@@ -767,8 +741,14 @@ S32 LLVFS::getMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type
BOOL LLVFS::checkAvailable(S32 max_size)
{
+ lockData();
+
blocks_length_map_t::iterator iter = mFreeBlocksByLength.lower_bound(max_size); // first entry >= size
- return (iter == mFreeBlocksByLength.end()) ? FALSE : TRUE;
+ const BOOL res(iter == mFreeBlocksByLength.end() ? FALSE : TRUE);
+
+ unlockData();
+
+ return res;
}
BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type, S32 max_size)
@@ -874,40 +854,42 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type
if (free_block)
{
+ // Save location where data is going, useFreeSpace will move free_block->mLocation;
+ U32 new_data_location = free_block->mLocation;
+
+ //mark the free block as used so it does not
+ //interfere with other operations such as addFreeBlock
+ useFreeSpace(free_block, max_size); // useFreeSpace takes ownership (and may delete) free_block
+
if (block->mLength > 0)
{
// create a new free block where this file used to be
LLVFSBlock *new_free_block = new LLVFSBlock(block->mLocation, block->mLength);
addFreeBlock(new_free_block);
-
+
if (block->mSize > 0)
{
// move the file into the new block
- U8 *buffer = new U8[block->mSize];
+ std::vector<U8> buffer(block->mSize);
fseek(mDataFP, block->mLocation, SEEK_SET);
- if (fread(buffer, block->mSize, 1, mDataFP) == 1)
+ if (fread(&buffer[0], block->mSize, 1, mDataFP) == 1)
{
- fseek(mDataFP, free_block->mLocation, SEEK_SET);
- if (fwrite(buffer, block->mSize, 1, mDataFP) != 1)
+ fseek(mDataFP, new_data_location, SEEK_SET);
+ if (fwrite(&buffer[0], block->mSize, 1, mDataFP) != 1)
{
llwarns << "Short write" << llendl;
}
} else {
llwarns << "Short read" << llendl;
}
-
- delete[] buffer;
}
}
- block->mLocation = free_block->mLocation;
+ block->mLocation = new_data_location;
block->mLength = max_size;
- // Must call useFreeSpace before sync(), as sync()
- // unlocks data structures.
- useFreeSpace(free_block, max_size);
sync(block);
@@ -1122,14 +1104,14 @@ S32 LLVFS::getData(const LLUUID &file_id, const LLAssetType::EType file_type, U8
}
}
- unlockData();
-
if (do_read)
{
fseek(mDataFP, location, SEEK_SET);
bytesread = (S32)fread(buffer, 1, length, mDataFP);
}
+ unlockData();
+
return bytesread;
}
@@ -1194,8 +1176,6 @@ S32 LLVFS::storeData(const LLUUID &file_id, const LLAssetType::EType file_type,
}
U32 file_location = location + block->mLocation;
- unlockData();
-
fseek(mDataFP, file_location, SEEK_SET);
S32 write_len = (S32)fwrite(buffer, 1, length, mDataFP);
if (write_len != length)
@@ -1204,7 +1184,6 @@ S32 LLVFS::storeData(const LLUUID &file_id, const LLAssetType::EType file_type,
}
// fflush(mDataFP);
- lockData();
if (location + length > block->mSize)
{
block->mSize = location + write_len;
@@ -1316,7 +1295,7 @@ void LLVFS::eraseBlockLength(LLVFSBlock *block)
}
if(!found_block)
{
- llwarns << "eraseBlock could not find block" << llendl;
+ llerrs << "eraseBlock could not find block" << llendl;
}
}
@@ -1453,7 +1432,7 @@ void LLVFS::addFreeBlock(LLVFSBlock *block)
// }
//}
-
+// length bytes from free_block are going to be used (so they are no longer free)
void LLVFS::useFreeSpace(LLVFSBlock *free_block, S32 length)
{
if (free_block->mLength == length)
@@ -1536,8 +1515,6 @@ void LLVFS::sync(LLVFSFileBlock *block, BOOL remove)
block->serialize(buffer);
}
- unlockData();
-
// If set_index_to_end, file pointer is already at seek_pos
// and we don't need to do anything. Only seek if not at end.
if (!set_index_to_end)
@@ -1549,11 +1526,10 @@ void LLVFS::sync(LLVFSFileBlock *block, BOOL remove)
{
llwarns << "Short write" << llendl;
}
-
+
+ // *NOTE: Why was this commented out?
// fflush(mIndexFP);
- lockData();
-
return;
}
@@ -1730,32 +1706,32 @@ void LLVFS::audit()
fflush(mIndexFP);
fseek(mIndexFP, 0, SEEK_END);
- long index_size = ftell(mIndexFP);
+ size_t index_size = ftell(mIndexFP);
fseek(mIndexFP, 0, SEEK_SET);
BOOL vfs_corrupt = FALSE;
- U8 *buffer = new U8[index_size];
+ std::vector<U8> buffer(index_size);
- if (fread(buffer, 1, index_size, mIndexFP) != index_size)
+ if (fread(&buffer[0], 1, index_size, mIndexFP) != index_size)
{
llwarns << "Index truncated" << llendl;
vfs_corrupt = TRUE;
}
- U8 *tmp_ptr = buffer;
+ size_t buf_offset = 0;
std::map<LLVFSFileSpecifier, LLVFSFileBlock*> found_files;
U32 cur_time = (U32)time(NULL);
std::vector<LLVFSFileBlock*> audit_blocks;
- while (!vfs_corrupt && tmp_ptr < buffer + index_size)
+ while (!vfs_corrupt && buf_offset < index_size)
{
LLVFSFileBlock *block = new LLVFSFileBlock();
audit_blocks.push_back(block);
- block->deserialize(tmp_ptr, (S32)(tmp_ptr - buffer));
- tmp_ptr += block->SERIAL_SIZE;
+ block->deserialize(&buffer[buf_offset], (S32)buf_offset);
+ buf_offset += block->SERIAL_SIZE;
// do sanity check on this block
if (block->mLength >= 0 &&
@@ -1814,8 +1790,6 @@ void LLVFS::audit()
}
}
- delete[] buffer;
-
if (!vfs_corrupt)
{
for (fileblock_map::iterator it = mFileBlocks.begin(); it != mFileBlocks.end(); ++it)
@@ -2041,31 +2015,30 @@ void LLVFS::dumpStatistics()
}
// Debug Only!
-LLString get_extension(LLAssetType::EType type)
+std::string get_extension(LLAssetType::EType type)
{
- LLString extension;
+ std::string extension;
switch(type)
{
- case LLAssetType::AT_TEXTURE:
- extension = ".j2c";
+ case LLAssetType::AT_TEXTURE:
+ extension = ".jp2"; // formerly ".j2c"
break;
- case LLAssetType::AT_SOUND:
+ case LLAssetType::AT_SOUND:
extension = ".ogg";
break;
- case LLAssetType::AT_SOUND_WAV:
+ case LLAssetType::AT_SOUND_WAV:
extension = ".wav";
break;
- case LLAssetType::AT_TEXTURE_TGA:
+ case LLAssetType::AT_TEXTURE_TGA:
extension = ".tga";
break;
- case LLAssetType::AT_IMAGE_JPEG:
- extension = ".jpeg";
- break;
- case LLAssetType::AT_ANIMATION:
+ case LLAssetType::AT_ANIMATION:
extension = ".lla";
break;
- default:
- extension = ".data";
+ default:
+ // Just use the asset server filename extension in most cases
+ extension += ".";
+ extension += LLAssetType::lookup(type);
break;
}
return extension;
@@ -2084,7 +2057,7 @@ void LLVFS::listFiles()
if (length != BLOCK_LENGTH_INVALID && size > 0)
{
LLUUID id = file_spec.mFileID;
- LLString extension = get_extension(file_spec.mFileType);
+ std::string extension = get_extension(file_spec.mFileType);
llinfos << " File: " << id
<< " Type: " << LLAssetType::getDesc(file_spec.mFileType)
<< " Size: " << size
@@ -2100,6 +2073,7 @@ void LLVFS::dumpFiles()
{
lockData();
+ S32 files_extracted = 0;
for (fileblock_map::iterator it = mFileBlocks.begin(); it != mFileBlocks.end(); ++it)
{
LLVFSFileSpecifier file_spec = it->first;
@@ -2110,23 +2084,28 @@ void LLVFS::dumpFiles()
{
LLUUID id = file_spec.mFileID;
LLAssetType::EType type = file_spec.mFileType;
- U8* buffer = new U8[size];
+ std::vector<U8> buffer(size);
unlockData();
- getData(id, type, buffer, 0, size);
+ getData(id, type, &buffer[0], 0, size);
lockData();
- LLString extension = get_extension(type);
- LLString filename = id.asString() + extension;
+ std::string extension = get_extension(type);
+ std::string filename = id.asString() + extension;
llinfos << " Writing " << filename << llendl;
- apr_file_t* file = ll_apr_file_open(filename, LL_APR_WB);
- ll_apr_file_write(file, buffer, size);
- apr_file_close(file);
- delete[] buffer;
+
+ LLAPRFile outfile;
+ outfile.open(filename, LL_APR_WB);
+ outfile.write(&buffer[0], size);
+ outfile.close();
+
+ files_extracted++;
}
}
unlockData();
+
+ llinfos << "Extracted " << files_extracted << " files out of " << mFileBlocks.size() << llendl;
}
//============================================================================
@@ -2134,7 +2113,7 @@ void LLVFS::dumpFiles()
//============================================================================
// static
-FILE *LLVFS::openAndLock(const char *filename, const char *mode, BOOL read_lock)
+LLFILE *LLVFS::openAndLock(const std::string& filename, const char* mode, BOOL read_lock)
{
#if LL_WINDOWS
@@ -2142,7 +2121,7 @@ FILE *LLVFS::openAndLock(const char *filename, const char *mode, BOOL read_lock)
#else
- FILE *fp;
+ LLFILE *fp;
int fd;
// first test the lock in a non-destructive way
@@ -2152,7 +2131,7 @@ FILE *LLVFS::openAndLock(const char *filename, const char *mode, BOOL read_lock)
fl.l_start = 0;
fl.l_len = 1;
#else // !LL_SOLARIS
- if (strstr(mode, "w"))
+ if (strchr(mode, 'w') != NULL)
{
fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
if (fp)
@@ -2192,7 +2171,7 @@ FILE *LLVFS::openAndLock(const char *filename, const char *mode, BOOL read_lock)
}
// static
-void LLVFS::unlockAndClose(FILE *fp)
+void LLVFS::unlockAndClose(LLFILE *fp)
{
if (fp)
{
diff --git a/indra/llvfs/llvfs.h b/indra/llvfs/llvfs.h
index a068c0d644..63f0f28933 100644
--- a/indra/llvfs/llvfs.h
+++ b/indra/llvfs/llvfs.h
@@ -2,30 +2,25 @@
* @file llvfs.h
* @brief Definition of virtual file system
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
*/
@@ -76,11 +71,25 @@ public:
class LLVFS
{
-public:
+private:
+ // Use createLLVFS() to open a VFS file
// Pass 0 to not presize
- LLVFS(const char *index_filename, const char *data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash);
+ LLVFS(const std::string& index_filename,
+ const std::string& data_filename,
+ const BOOL read_only,
+ const U32 presize,
+ const BOOL remove_after_crash);
+public:
~LLVFS();
+ // Use this function normally to create LLVFS files
+ // Pass 0 to not presize
+ static LLVFS * createLLVFS(const std::string& index_filename,
+ const std::string& data_filename,
+ const BOOL read_only,
+ const U32 presize,
+ const BOOL remove_after_crash);
+
BOOL isValid() const { return (VFSVALID_OK == mValid); }
EVFSValid getValidState() const { return mValid; }
@@ -131,7 +140,7 @@ protected:
void sync(LLVFSFileBlock *block, BOOL remove = FALSE);
void presizeDataFile(const U32 size);
- static FILE *openAndLock(const char *filename, const char *mode, BOOL read_lock);
+ static LLFILE *openAndLock(const std::string& filename, const char* mode, BOOL read_lock);
static void unlockAndClose(FILE *fp);
// Can initiate LRU-based file removal to make space.
@@ -153,13 +162,13 @@ protected:
typedef std::multimap<U32, LLVFSBlock*> blocks_location_map_t;
blocks_location_map_t mFreeBlocksByLocation;
- FILE *mDataFP;
- FILE *mIndexFP;
+ LLFILE *mDataFP;
+ LLFILE *mIndexFP;
std::deque<S32> mIndexHoles;
- char *mIndexFilename;
- char *mDataFilename;
+ std::string mIndexFilename;
+ std::string mDataFilename;
BOOL mReadOnly;
EVFSValid mValid;
diff --git a/indra/llvfs/llvfsthread.cpp b/indra/llvfs/llvfsthread.cpp
index fbfbdffaf3..254f8b55ba 100644
--- a/indra/llvfs/llvfsthread.cpp
+++ b/indra/llvfs/llvfsthread.cpp
@@ -2,35 +2,29 @@
* @file llvfsthread.cpp
* @brief LLVFSThread implementation
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
-#include "llmath.h"
#include "llvfsthread.h"
#include "llstl.h"
diff --git a/indra/llvfs/llvfsthread.h b/indra/llvfs/llvfsthread.h
index 6028199055..95f3c857c6 100644
--- a/indra/llvfs/llvfsthread.h
+++ b/indra/llvfs/llvfsthread.h
@@ -2,30 +2,25 @@
* @file llvfsthread.h
* @brief LLVFSThread definition
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -87,9 +82,9 @@ public:
}
std::string getFilename()
{
- char tbuf[40]; /* Flawfinder: ignore */
- mFileID.toString(tbuf);
- return std::string(tbuf);
+ std::string tstring;
+ mFileID.toString(tstring);
+ return tstring;
}
/*virtual*/ bool processRequest();
diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp
new file mode 100644
index 0000000000..bcffa449c8
--- /dev/null
+++ b/indra/llvfs/tests/lldir_test.cpp
@@ -0,0 +1,260 @@
+/**
+ * @file lldir_test.cpp
+ * @date 2008-05
+ * @brief LLDir test cases.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../lldir.h"
+
+#include "../test/lltut.h"
+
+
+namespace tut
+{
+ 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.
+
+ ensure_equals("getBaseFileName/rn-no-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(rawFileNullExt, false),
+ "foo.");
+
+ ensure_equals("getBaseFileName/rn-no-ext/strip-exten",
+ gDirUtilp->getBaseFileName(rawFileNullExt, true),
+ "foo");
+
+ // .bAr
+ // interesting case - with no basename, this IS the basename, not the extension.
+
+ ensure_equals("getBaseFileName/e-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(rawExt, false),
+ ".bAr");
+
+ ensure_equals("getBaseFileName/e-ext/strip-exten",
+ gDirUtilp->getBaseFileName(rawExt, true),
+ ".bAr");
+
+ // .
+
+ ensure_equals("getBaseFileName/d/no-strip-exten",
+ gDirUtilp->getBaseFileName(rawDot, false),
+ ".");
+
+ ensure_equals("getBaseFileName/d/strip-exten",
+ gDirUtilp->getBaseFileName(rawDot, true),
+ ".");
+
+ // aa/bb/cc/dd/ee[.eXt]
+
+ ensure_equals("getBaseFileName/no-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(pathNoExt, false),
+ "ee");
+
+ ensure_equals("getBaseFileName/no-ext/strip-exten",
+ gDirUtilp->getBaseFileName(pathNoExt, true),
+ "ee");
+
+ ensure_equals("getBaseFileName/ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(pathExt, false),
+ "ee.eXt");
+
+ ensure_equals("getBaseFileName/ext/strip-exten",
+ gDirUtilp->getBaseFileName(pathExt, true),
+ "ee");
+
+ // aa/bb/cc.dd/ee[.eXt]
+
+ ensure_equals("getBaseFileName/d-no-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(dottedPathNoExt, false),
+ "ee");
+
+ ensure_equals("getBaseFileName/d-no-ext/strip-exten",
+ gDirUtilp->getBaseFileName(dottedPathNoExt, true),
+ "ee");
+
+ ensure_equals("getBaseFileName/d-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(dottedPathExt, false),
+ "ee.eXt");
+
+ ensure_equals("getBaseFileName/d-ext/strip-exten",
+ gDirUtilp->getBaseFileName(dottedPathExt, true),
+ "ee");
+ }
+
+ template<> template<>
+ void LLDirTest_object_t::test<3>()
+ // getDirName
+ {
+ std::string delim = gDirUtilp->getDirDelimiter();
+ std::string rawFile = "foo";
+ std::string rawFileExt = "foo.bAr";
+ std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee";
+ std::string pathExt = pathNoExt + ".eXt";
+ std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee";
+ std::string dottedPathExt = dottedPathNoExt + ".eXt";
+
+ // foo[.bAr]
+
+ ensure_equals("getDirName/r-no-ext",
+ gDirUtilp->getDirName(rawFile),
+ "");
+
+ ensure_equals("getDirName/r-ext",
+ gDirUtilp->getDirName(rawFileExt),
+ "");
+
+ // aa/bb/cc/dd/ee[.eXt]
+
+ ensure_equals("getDirName/no-ext",
+ gDirUtilp->getDirName(pathNoExt),
+ "aa" + delim + "bb" + delim + "cc" + delim + "dd");
+
+ ensure_equals("getDirName/ext",
+ gDirUtilp->getDirName(pathExt),
+ "aa" + delim + "bb" + delim + "cc" + delim + "dd");
+
+ // aa/bb/cc.dd/ee[.eXt]
+
+ ensure_equals("getDirName/d-no-ext",
+ gDirUtilp->getDirName(dottedPathNoExt),
+ "aa" + delim + "bb" + delim + "cc.dd");
+
+ ensure_equals("getDirName/d-ext",
+ gDirUtilp->getDirName(dottedPathExt),
+ "aa" + delim + "bb" + delim + "cc.dd");
+ }
+
+ template<> template<>
+ void LLDirTest_object_t::test<4>()
+ // getExtension
+ {
+ std::string delim = gDirUtilp->getDirDelimiter();
+ std::string rawFile = "foo";
+ std::string rawFileExt = "foo.bAr";
+ std::string rawFileNullExt = "foo.";
+ std::string rawExt = ".bAr";
+ std::string rawDot = ".";
+ std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee";
+ std::string pathExt = pathNoExt + ".eXt";
+ std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee";
+ std::string dottedPathExt = dottedPathNoExt + ".eXt";
+
+ // foo[.bAr]
+
+ ensure_equals("getExtension/r-no-ext",
+ gDirUtilp->getExtension(rawFile),
+ "");
+
+ ensure_equals("getExtension/r-ext",
+ gDirUtilp->getExtension(rawFileExt),
+ "bar");
+
+ // foo.
+
+ ensure_equals("getExtension/rn-no-ext",
+ gDirUtilp->getExtension(rawFileNullExt),
+ "");
+
+ // .bAr
+ // interesting case - with no basename, this IS the basename, not the extension.
+
+ ensure_equals("getExtension/e-ext",
+ gDirUtilp->getExtension(rawExt),
+ "");
+
+ // .
+
+ ensure_equals("getExtension/d",
+ gDirUtilp->getExtension(rawDot),
+ "");
+
+ // aa/bb/cc/dd/ee[.eXt]
+
+ ensure_equals("getExtension/no-ext",
+ gDirUtilp->getExtension(pathNoExt),
+ "");
+
+ ensure_equals("getExtension/ext",
+ gDirUtilp->getExtension(pathExt),
+ "ext");
+
+ // aa/bb/cc.dd/ee[.eXt]
+
+ ensure_equals("getExtension/d-no-ext",
+ gDirUtilp->getExtension(dottedPathNoExt),
+ "");
+
+ ensure_equals("getExtension/d-ext",
+ gDirUtilp->getExtension(dottedPathExt),
+ "ext");
+ }
+}
+