summaryrefslogtreecommitdiff
path: root/indra/llvfs
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llvfs')
-rw-r--r--indra/llvfs/CMakeLists.txt15
-rw-r--r--indra/llvfs/lldir.cpp111
-rw-r--r--indra/llvfs/lldir.h44
-rw-r--r--indra/llvfs/lldir_linux.cpp48
-rw-r--r--indra/llvfs/lldir_linux.h6
-rw-r--r--indra/llvfs/lldir_mac.cpp54
-rw-r--r--indra/llvfs/lldir_mac.h6
-rw-r--r--indra/llvfs/lldir_solaris.cpp21
-rw-r--r--indra/llvfs/lldir_solaris.h3
-rw-r--r--indra/llvfs/lldir_win32.cpp51
-rw-r--r--indra/llvfs/lldir_win32.h6
-rw-r--r--indra/llvfs/lldirguard.h78
-rw-r--r--indra/llvfs/lllfsthread.cpp4
-rw-r--r--indra/llvfs/lllfsthread.h2
-rwxr-xr-xindra/llvfs/llpidlock.cpp18
-rwxr-xr-xindra/llvfs/llpidlock.h19
-rw-r--r--indra/llvfs/llvfile.cpp6
-rw-r--r--indra/llvfs/llvfs.cpp2
-rw-r--r--indra/llvfs/tests/lldir_test.cpp266
19 files changed, 638 insertions, 122 deletions
diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
index cc0297e3dc..05c7c7860c 100644
--- a/indra/llvfs/CMakeLists.txt
+++ b/indra/llvfs/CMakeLists.txt
@@ -23,6 +23,7 @@ set(llvfs_HEADER_FILES
CMakeLists.txt
lldir.h
+ lldirguard.h
lllfsthread.h
llpidlock.h
llvfile.h
@@ -64,3 +65,17 @@ if (DARWIN)
find_library(CARBON_LIBRARY Carbon)
target_link_libraries(llvfs ${CARBON_LIBRARY})
endif (DARWIN)
+
+
+# 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}")
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index d6a6eca341..da4abde451 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -41,7 +41,9 @@
#endif
#include "lldir.h"
+
#include "llerror.h"
+#include "lltimer.h" // ms_sleep()
#include "lluuid.h"
#if LL_WINDOWS
@@ -125,16 +127,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
+ 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)
@@ -194,6 +200,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;
}
@@ -287,13 +298,13 @@ const std::string& LLDir::getDefaultSkinDir() const
const std::string LLDir::getSkinBaseDir() const
{
- std::string dir = getAppRODataDir();
- dir += mDirDelimiter;
- dir += "skins";
-
- return dir;
+ return mSkinBaseDir;
}
+const std::string &LLDir::getLLPluginDir() const
+{
+ return mLLPluginDir;
+}
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const
{
@@ -319,25 +330,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:
@@ -348,6 +353,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:
@@ -372,28 +382,38 @@ 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:
- // prefix = getSkinDir();
- // prefix += mDirDelimiter;
- // prefix += "html";
- // break;
+ case LL_PATH_SKINS:
+ prefix = getSkinBaseDir();
+ break;
- case LL_PATH_MOZILLA_PROFILE:
- prefix = getOSUserAppDir();
+ case LL_PATH_LOCAL_ASSETS:
+ prefix = getAppRODataDir();
prefix += mDirDelimiter;
- prefix += "browser_profile";
+ prefix += "local_assets";
break;
case LL_PATH_EXECUTABLE:
prefix = getExecutableDir();
break;
+ case LL_PATH_FONTS:
+ prefix = getAppRODataDir();
+ prefix += mDirDelimiter;
+ prefix += "fonts";
+ break;
+
default:
llassert(0);
}
@@ -409,6 +429,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
filename = subdir1 + mDirDelimiter + filename;
}
+ if (prefix.empty())
+ {
+ llwarns << "prefix is empty, possible bad filename" << llendl;
+ }
+
std::string expanded_filename;
if (!filename.empty())
{
@@ -465,6 +490,8 @@ std::string LLDir::getDirName(const std::string& filepath) const
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);
@@ -488,11 +515,14 @@ std::string LLDir::findSkinnedFilename(const std::string &subdir1, const std::st
std::string subdirs = ((subdir1.empty() ? "" : mDirDelimiter) + subdir1)
+ ((subdir2.empty() ? "" : mDirDelimiter) + subdir2);
- std::string found_file = findFile(filename,
- getUserSkinDir() + subdirs, // first look in user skin override
- getSkinDir() + subdirs, // then in current skin
- getDefaultSkinDir() + subdirs); // and last in default skin
+ 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;
}
@@ -537,7 +567,7 @@ std::string LLDir::getForbiddenFileChars()
void LLDir::setLindenUserDir(const std::string &first, const std::string &last)
{
- // if both first and last aren't set, assume we're grabbing the cached dir
+ // if both first and last aren't set, that's bad.
if (!first.empty() && !last.empty())
{
// some platforms have case-sensitive filesystems, so be
@@ -551,10 +581,11 @@ void LLDir::setLindenUserDir(const std::string &first, const std::string &last)
mLindenUserDir += firstlower;
mLindenUserDir += "_";
mLindenUserDir += lastlower;
+ llinfos << "Got name for LLDir::setLindenUserDir(first='" << first << "', last='" << last << "')" << llendl;
}
else
{
- llerrs << "Invalid name for LLDir::setLindenUserDir" << llendl;
+ llerrs << "Invalid name for LLDir::setLindenUserDir(first='" << first << "', last='" << last << "')" << llendl;
}
dumpCurrentDirectories();
@@ -597,9 +628,7 @@ void LLDir::setPerAccountChatLogsDir(const std::string &first, const std::string
void LLDir::setSkinFolder(const std::string &skin_folder)
{
- mSkinDir = getAppRODataDir();
- mSkinDir += mDirDelimiter;
- mSkinDir += "skins";
+ mSkinDir = getSkinBaseDir();
mSkinDir += mDirDelimiter;
mSkinDir += skin_folder;
@@ -613,9 +642,7 @@ void LLDir::setSkinFolder(const std::string &skin_folder)
// base skin which is used as fallback for all skinned files
// e.g. c:\program files\secondlife\skins\default
- mDefaultSkinDir = getAppRODataDir();
- mDefaultSkinDir += mDirDelimiter;
- mDefaultSkinDir += "skins";
+ mDefaultSkinDir = getSkinBaseDir();
mDefaultSkinDir += mDirDelimiter;
mDefaultSkinDir += "default";
}
@@ -660,12 +687,8 @@ void LLDir::dumpCurrentDirectories()
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;
-
-#if LL_LIBXUL_ENABLED
- LL_DEBUGS2("AppInit","Directories") << " HTML Path: " << getExpandedFilename( LL_PATH_HTML, "" ) << llendl;
- LL_DEBUGS2("AppInit","Directories") << " Mozilla Profile Path: " << getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ) << llendl;
-#endif
}
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index 760b6512a5..9067d75bac 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -38,26 +38,27 @@
#define MAX_PATH MAXPATHLEN
#endif
-// these numbers *may* get serialized, so we need to be explicit
+// 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_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;
@@ -68,8 +69,13 @@ class LLDir
LLDir();
virtual ~LLDir();
- virtual void initAppDirs(const std::string &app_name) = 0;
- public:
+ // 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
@@ -79,7 +85,12 @@ class LLDir
virtual std::string getCurPath() = 0;
virtual BOOL fileExists(const std::string &filename) const = 0;
- const std::string findFile(const std::string &filename, const std::string searchPath1 = "", const std::string searchPath2 = "", const std::string searchPath3 = "") const;
+ const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const;
+ const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const;
+
+ virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell
+ virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so')
+
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
@@ -100,6 +111,7 @@ class LLDir
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;
@@ -153,9 +165,11 @@ protected:
std::string mDefaultCacheDir; // default cache diretory
std::string mOSCacheDir; // operating system cache dir
std::string mDirDelimiter;
+ 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 8ff8c5d1c6..a9736560ec 100644
--- a/indra/llvfs/lldir_linux.cpp
+++ b/indra/llvfs/lldir_linux.cpp
@@ -99,9 +99,23 @@ LLDir_Linux::LLDir_Linux()
#else
mAppRODataDir = tmp_str;
#endif
+ 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 = getCurrentUserHome(tmp_str);
mOSUserAppDir = "";
- mLindenUserDir = tmp_str;
+ mLindenUserDir = "";
char path [32]; /* Flawfinder: ignore */
@@ -128,6 +142,8 @@ LLDir_Linux::LLDir_Linux()
}
}
+ mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
+
// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
mTempDir = "/tmp";
}
@@ -139,8 +155,15 @@ 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;
std::string upper_app_name(app_name);
@@ -203,15 +226,6 @@ void LLDir_Linux::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,""));
- 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");
}
@@ -370,3 +384,15 @@ BOOL LLDir_Linux::fileExists(const std::string &filename) const
}
}
+
+/*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 20b408f8dc..1fec15c5c6 100644
--- a/indra/llvfs/lldir_linux.h
+++ b/indra/llvfs/lldir_linux.h
@@ -44,7 +44,8 @@ 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);
@@ -52,6 +53,9 @@ public:
virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*virtual*/ BOOL fileExists(const std::string &filename) const;
+ /*virtual*/ std::string getLLPluginLauncher();
+ /*virtual*/ std::string getLLPluginFilename(std::string base_name);
+
private:
DIR *mDirp;
int mCurrentDirIndex;
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index d4dee5a02e..7bc6f63e1f 100644
--- a/indra/llvfs/lldir_mac.cpp
+++ b/indra/llvfs/lldir_mac.cpp
@@ -68,7 +68,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))
@@ -142,9 +143,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)
@@ -190,6 +216,8 @@ LLDir_Mac::LLDir_Mac()
}
mWorkingDir = getCurPath();
+
+ mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin";
CFRelease(executableURLRef);
executableURLRef = NULL;
@@ -203,8 +231,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();
@@ -388,4 +423,17 @@ BOOL LLDir_Mac::fileExists(const std::string &filename) const
}
+/*virtual*/ std::string LLDir_Mac::getLLPluginLauncher()
+{
+ return gDirUtilp->getAppRODataDir() + gDirUtilp->getDirDelimiter() +
+ "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 28d48a0b6a..834acc7262 100644
--- a/indra/llvfs/lldir_mac.h
+++ b/indra/llvfs/lldir_mac.h
@@ -43,7 +43,8 @@ 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();
@@ -52,6 +53,9 @@ public:
virtual void getRandomFileInDir(const std::string &dirname, const std::string &ask, std::string &fname);
virtual BOOL fileExists(const std::string &filename) const;
+ /*virtual*/ std::string getLLPluginLauncher();
+ /*virtual*/ std::string getLLPluginFilename(std::string base_name);
+
private:
int mCurrentDirIndex;
int mCurrentDirCount;
diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp
index 9553d923aa..8ac5a41e93 100644
--- a/indra/llvfs/lldir_solaris.cpp
+++ b/indra/llvfs/lldir_solaris.cpp
@@ -100,7 +100,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 */
@@ -161,6 +161,8 @@ LLDir_Solaris::LLDir_Solaris()
}
}
+ mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
+
// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
mTempDir = "/tmp";
}
@@ -172,8 +174,14 @@ 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;
std::string upper_app_name(app_name);
@@ -236,15 +244,6 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,""));
- 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");
}
diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h
index 139754ba28..1fa8348355 100644
--- a/indra/llvfs/lldir_solaris.h
+++ b/indra/llvfs/lldir_solaris.h
@@ -44,7 +44,8 @@ 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);
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 19b9bcc6ea..4eb10c842b 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -121,15 +121,21 @@ LLDir_Win32::LLDir_Win32()
GetCurrentDirectory(MAX_PATH, w_str);
mExecutableDir = utf16str_to_utf8str(llutf16string(w_str));
#endif
-
- // When running in a dev tree, app_settings is under indra/newview/
- // but in production it is under Program Files/SecondLife/
- // Attempt to detect which one we're using. JC
- if (mExecutableDir.find("indra") != std::string::npos)
- mAppRODataDir = getCurPath();
- else
- mAppRODataDir = mExecutableDir;
+ mAppRODataDir = ".";
+
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+
+ 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));
+ }
+ llinfos << "mAppRODataDir = " << mAppRODataDir << llendl;
// Build the default cache directory
mDefaultCacheDir = buildSLOSCacheDir();
@@ -143,6 +149,8 @@ LLDir_Win32::LLDir_Win32()
llwarns << "Couldn't create LL_PATH_CACHE dir " << mDefaultCacheDir << llendl;
}
}
+
+ mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
}
LLDir_Win32::~LLDir_Win32()
@@ -151,8 +159,15 @@ 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 += "\\";
@@ -197,15 +212,14 @@ void LLDir_Win32::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,""));
+ 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");
}
@@ -378,6 +392,19 @@ BOOL LLDir_Win32::fileExists(const std::string &filename) const
}
+/*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 8710ca50e1..c2acfa6bd4 100644
--- a/indra/llvfs/lldir_win32.h
+++ b/indra/llvfs/lldir_win32.h
@@ -41,7 +41,8 @@ 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);
@@ -49,6 +50,9 @@ public:
/*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*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..85366120d8
--- /dev/null
+++ b/indra/llvfs/lldirguard.h
@@ -0,0 +1,78 @@
+/**
+ * @file lldirguard.h
+ * @brief Protect working directory from being changed in scope.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * 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://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * 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://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * 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.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/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 704e1ab142..e85cc437f4 100644
--- a/indra/llvfs/lllfsthread.cpp
+++ b/indra/llvfs/lllfsthread.cpp
@@ -189,7 +189,7 @@ bool LLLFSThread::Request::processRequest()
{
llassert(mOffset >= 0);
LLAPRFile infile ;
- infile.open(mThread->getLocalAPRFilePool(), mFileName, LL_APR_RB);
+ infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool());
if (!infile.getFileHandle())
{
llwarns << "LLLFS: Unable to read file: " << mFileName << llendl;
@@ -213,7 +213,7 @@ bool LLLFSThread::Request::processRequest()
if (mOffset < 0)
flags |= APR_APPEND;
LLAPRFile outfile ;
- outfile.open(mThread->getLocalAPRFilePool(), mFileName, flags);
+ outfile.open(mFileName, flags, mThread->getLocalAPRFilePool());
if (!outfile.getFileHandle())
{
llwarns << "LLLFS: Unable to write file: " << mFileName << llendl;
diff --git a/indra/llvfs/lllfsthread.h b/indra/llvfs/lllfsthread.h
index 5a11cb33d7..3139693302 100644
--- a/indra/llvfs/lllfsthread.h
+++ b/indra/llvfs/lllfsthread.h
@@ -39,7 +39,7 @@
#include <set>
#include "llapr.h"
-
+#include "llpointer.h"
#include "llqueuedthread.h"
//============================================================================
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
index e231002a52..95e3692e10 100755
--- a/indra/llvfs/llpidlock.cpp
+++ b/indra/llvfs/llpidlock.cpp
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
- * Copyright (c) 2007, Linden Research, Inc.
+ * Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -13,12 +13,13 @@
* ("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
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* 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
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -40,6 +41,15 @@
#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);
@@ -61,7 +71,7 @@ class LLPidLockFile
mSaving(FALSE), mWaiting(FALSE),
mClean(TRUE), mPID(getpid())
{
- mLockName = gDirUtilp->getTempDir() + "/savelock";
+ mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
}
bool requestLock(LLNameTable<void *> *name_table, bool autosave,
bool force_immediate=FALSE, F32 timeout=300.0);
diff --git a/indra/llvfs/llpidlock.h b/indra/llvfs/llpidlock.h
index 44ed8caf46..496e99cf5a 100755
--- a/indra/llvfs/llpidlock.h
+++ b/indra/llvfs/llpidlock.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
- * Copyright (c) 2001-2007, Linden Research, Inc.
+ * Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("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
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* 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
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -36,17 +37,9 @@
class LLSD;
class LLFrameTimer;
-#if LL_WINDOWS //For windows platform.
-
-#include <windows.h>
-
-#define getpid GetCurrentProcessId
-
-#else //Everyone Else
-
+#if !LL_WINDOWS //For non-windows platforms.
#include <signal.h>
-
-#endif //Everyone else.
+#endif
namespace LLPidLock
{
diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp
index 6b1563bab1..5fdf41188d 100644
--- a/indra/llvfs/llvfile.cpp
+++ b/indra/llvfs/llvfile.cpp
@@ -44,6 +44,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;
@@ -318,7 +320,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)
{
@@ -426,7 +428,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/llvfs.cpp b/indra/llvfs/llvfs.cpp
index ef8c4d6c7f..9ce1e75d06 100644
--- a/indra/llvfs/llvfs.cpp
+++ b/indra/llvfs/llvfs.cpp
@@ -46,7 +46,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
diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp
new file mode 100644
index 0000000000..9befa59477
--- /dev/null
+++ b/indra/llvfs/tests/lldir_test.cpp
@@ -0,0 +1,266 @@
+/**
+ * @file lldir_test.cpp
+ * @date 2008-05
+ * @brief LLDir test cases.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * 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://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * 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://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * 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.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/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");
+ }
+}
+