diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llvfs/lldir_mac.cpp |
Print done when done.
Diffstat (limited to 'indra/llvfs/lldir_mac.cpp')
-rw-r--r-- | indra/llvfs/lldir_mac.cpp | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp new file mode 100644 index 0000000000..591241478d --- /dev/null +++ b/indra/llvfs/lldir_mac.cpp @@ -0,0 +1,362 @@ +/** + * @file lldir_mac.cpp + * @brief Implementation of directory utilities for linux + * + * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#if LL_DARWIN + +#include "linden_common.h" + +#include "lldir_mac.h" +#include "llerror.h" +#include "llrand.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <glob.h> + +#include <Carbon/Carbon.h> + +// -------------------------------------------------------------------------------- + +static OSStatus CFCreateDirectory(FSRef *parentRef, CFStringRef name, FSRef *newRef) +{ + OSStatus result = noErr; + HFSUniStr255 uniStr; + + uniStr.length = CFStringGetLength(name); + CFStringGetCharacters(name, CFRangeMake(0, uniStr.length), uniStr.unicode); + result = FSMakeFSRefUnicode(parentRef, uniStr.length, uniStr.unicode, kTextEncodingMacRoman, newRef); + if (result != noErr) + { + result = FSCreateDirectoryUnicode(parentRef, uniStr.length, uniStr.unicode, 0, NULL, newRef, NULL, NULL); + } + + return result; +} + +// -------------------------------------------------------------------------------- + +static void CFStringRefToLLString(CFStringRef stringRef, std::string &llString, bool releaseWhenDone) +{ + if (stringRef) + { + long bufferSize = CFStringGetLength(stringRef) + 1; + char* buffer = new char[bufferSize]; + memset(buffer, 0, bufferSize); + if (CFStringGetCString(stringRef, buffer, bufferSize, kCFStringEncodingUTF8)) + llString = buffer; + delete[] buffer; + if (releaseWhenDone) + CFRelease(stringRef); + } +} + +// -------------------------------------------------------------------------------- + +static void CFURLRefToLLString(CFURLRef urlRef, std::string &llString, bool releaseWhenDone) +{ + if (urlRef) + { + CFURLRef absoluteURLRef = CFURLCopyAbsoluteURL(urlRef); + if (absoluteURLRef) + { + CFStringRef stringRef = CFURLCopyFileSystemPath(absoluteURLRef, kCFURLPOSIXPathStyle); + CFStringRefToLLString(stringRef, llString, true); + CFRelease(absoluteURLRef); + } + if (releaseWhenDone) + CFRelease(urlRef); + } +} + +// -------------------------------------------------------------------------------- + +static void FSRefToLLString(FSRef *fsRef, std::string &llString) +{ + OSStatus error = noErr; + char path[MAX_PATH]; + + error = FSRefMakePath(fsRef, (UInt8*) path, sizeof(path)); + if (error == noErr) + llString = path; +} + +// -------------------------------------------------------------------------------- + +LLDir_Mac::LLDir_Mac() +{ + mDirDelimiter = "/"; + mCurrentDirIndex = -1; + mCurrentDirCount = -1; + + CFBundleRef mainBundleRef = NULL; + CFURLRef executableURLRef = NULL; + CFStringRef stringRef = NULL; + OSStatus error = noErr; + FSRef fileRef; + CFStringRef secondLifeString = CFSTR("SecondLife"); + + mainBundleRef = CFBundleGetMainBundle(); + + executableURLRef = CFBundleCopyExecutableURL(mainBundleRef); + + if (executableURLRef != NULL) + { + // mExecutablePathAndName + CFURLRefToLLString(executableURLRef, mExecutablePathAndName, false); + + // mExecutableFilename + stringRef = CFURLCopyLastPathComponent(executableURLRef); + CFStringRefToLLString(stringRef, mExecutableFilename, true); + + // mExecutableDir + CFURLRef executableParentURLRef = CFURLCreateCopyDeletingLastPathComponent(NULL, executableURLRef); + CFURLRefToLLString(executableParentURLRef, mExecutableDir, true); + + // mAppRODataDir + CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef); + CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true); + + // mOSUserDir + error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef); + if (error == noErr) + { + FSRef newFileRef; + + // Create the directory + error = CFCreateDirectory(&fileRef, secondLifeString, &newFileRef); + if (error == noErr) + { + // Save the full path to the folder + FSRefToLLString(&newFileRef, mOSUserDir); + + // Create our sub-dirs + (void) CFCreateDirectory(&newFileRef, CFSTR("data"), 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); + } + } + + // mOSUserAppDir + mOSUserAppDir = mOSUserDir; + + // mTempDir + error = FSFindFolder(kOnAppropriateDisk, kTemporaryFolderType, true, &fileRef); + if (error == noErr) + { + FSRef tempRef; + error = CFCreateDirectory(&fileRef, secondLifeString, &tempRef); + if (error == noErr) + FSRefToLLString(&tempRef, mTempDir); + } + + // Set the working dir to <bundle>/Contents/Resources + (void) chdir(mAppRODataDir.c_str()); + + // Canonically, since we set it here... + mWorkingDir = mAppRODataDir; + + CFRelease(executableURLRef); + executableURLRef = NULL; + } +} + +LLDir_Mac::~LLDir_Mac() +{ +} + +// Implementation + + +void LLDir_Mac::initAppDirs(const std::string &app_name) +{ + mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem"); + + //dumpCurrentDirectories(); +} + +U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &mask) +{ + U32 file_count = 0; + glob_t g; + + std::string tmp_str; + tmp_str = dirname; + tmp_str += mask; + + if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) + { + file_count = g.gl_pathc; + + globfree(&g); + } + + return (file_count); +} + +// get the next file in the directory +// automatically wrap if we've hit the end +BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) +{ + glob_t g; + BOOL result = FALSE; + fname = ""; + + if(!(dirname == mCurrentDir)) + { + // different dir specified, close old search + mCurrentDirIndex = -1; + mCurrentDirCount = -1; + mCurrentDir = dirname; + } + + std::string tmp_str; + tmp_str = dirname; + tmp_str += mask; + + if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) + { + if(g.gl_pathc > 0) + { + if(g.gl_pathc != mCurrentDirCount) + { + // Number of matches has changed since the last search, meaning a file has been added or deleted. + // Reset the index. + mCurrentDirIndex = -1; + mCurrentDirCount = g.gl_pathc; + } + + mCurrentDirIndex++; + + if((mCurrentDirIndex >= g.gl_pathc) && wrap) + { + mCurrentDirIndex = 0; + } + + if(mCurrentDirIndex < g.gl_pathc) + { +// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; + + // The API wants just the filename, not the full path. + //fname = g.gl_pathv[mCurrentDirIndex]; + + char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); + + if(s == NULL) + s = g.gl_pathv[mCurrentDirIndex]; + else if(s[0] == '/') + s++; + + fname = s; + + result = TRUE; + } + } + + globfree(&g); + } + + return(result); +} + +// get a random file in the directory +void LLDir_Mac::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) +{ + U32 which_file; + glob_t g; + fname = ""; + + std::string tmp_str; + tmp_str = dirname; + tmp_str += mask; + + if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) + { + if(g.gl_pathc > 0) + { + + which_file = gLindenLabRandomNumber.llrand() % g.gl_pathc; + +// llinfos << "getRandomFileInDir: returning number " << which_file << ", path is " << g.gl_pathv[which_file] << llendl; + // The API wants just the filename, not the full path. + //fname = g.gl_pathv[which_file]; + + char *s = strrchr(g.gl_pathv[which_file], '/'); + + if(s == NULL) + s = g.gl_pathv[which_file]; + else if(s[0] == '/') + s++; + + fname = s; + } + + globfree(&g); + } +} + +S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask) +{ + glob_t g; + S32 result = 0; + + std::string tmp_str; + tmp_str = dirname; + tmp_str += mask; + + if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) + { + int i; + + for(i = 0; i < g.gl_pathc; i++) + { +// llinfos << "deleteFilesInDir: deleting number " << i << ", path is " << g.gl_pathv[i] << llendl; + + if(unlink(g.gl_pathv[i]) != 0) + { + result = errno; + + llwarns << "Problem removing " << g.gl_pathv[i] << " - errorcode: " + << result << llendl; + } + } + + globfree(&g); + } + + return(result); +} + +std::string LLDir_Mac::getCurPath() +{ + char tmp_str[LL_MAX_PATH]; + getcwd(tmp_str, LL_MAX_PATH); + return tmp_str; +} + + + +BOOL LLDir_Mac::fileExists(const std::string &filename) +{ + struct stat stat_data; + // Check the age of the file + // Now, we see if the files we've gathered are recent... + int res = stat(filename.c_str(), &stat_data); + if (!res) + { + return TRUE; + } + else + { + return FALSE; + } +} + + +#endif // LL_DARWIN |