summaryrefslogtreecommitdiff
path: root/indra/llvfs/lldir_mac.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llvfs/lldir_mac.cpp
Print done when done.
Diffstat (limited to 'indra/llvfs/lldir_mac.cpp')
-rw-r--r--indra/llvfs/lldir_mac.cpp362
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