00001
00032 #if LL_DARWIN
00033
00034 #include "linden_common.h"
00035
00036 #include "lldir_mac.h"
00037 #include "llerror.h"
00038 #include "llrand.h"
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #include <unistd.h>
00042 #include <glob.h>
00043
00044 #include <Carbon/Carbon.h>
00045
00046
00047
00048 static OSStatus CFCreateDirectory(FSRef *parentRef, CFStringRef name, FSRef *newRef)
00049 {
00050 OSStatus result = noErr;
00051 HFSUniStr255 uniStr;
00052
00053 uniStr.length = CFStringGetLength(name);
00054 CFStringGetCharacters(name, CFRangeMake(0, uniStr.length), uniStr.unicode);
00055 result = FSMakeFSRefUnicode(parentRef, uniStr.length, uniStr.unicode, kTextEncodingMacRoman, newRef);
00056 if (result != noErr)
00057 {
00058 result = FSCreateDirectoryUnicode(parentRef, uniStr.length, uniStr.unicode, 0, NULL, newRef, NULL, NULL);
00059 }
00060
00061 return result;
00062 }
00063
00064
00065
00066 static void CFStringRefToLLString(CFStringRef stringRef, std::string &llString, bool releaseWhenDone)
00067 {
00068 if (stringRef)
00069 {
00070 long bufferSize = CFStringGetLength(stringRef) + 1;
00071 char* buffer = new char[bufferSize];
00072 memset(buffer, 0, bufferSize);
00073 if (CFStringGetCString(stringRef, buffer, bufferSize, kCFStringEncodingUTF8))
00074 llString = buffer;
00075 delete[] buffer;
00076 if (releaseWhenDone)
00077 CFRelease(stringRef);
00078 }
00079 }
00080
00081
00082
00083 static void CFURLRefToLLString(CFURLRef urlRef, std::string &llString, bool releaseWhenDone)
00084 {
00085 if (urlRef)
00086 {
00087 CFURLRef absoluteURLRef = CFURLCopyAbsoluteURL(urlRef);
00088 if (absoluteURLRef)
00089 {
00090 CFStringRef stringRef = CFURLCopyFileSystemPath(absoluteURLRef, kCFURLPOSIXPathStyle);
00091 CFStringRefToLLString(stringRef, llString, true);
00092 CFRelease(absoluteURLRef);
00093 }
00094 if (releaseWhenDone)
00095 CFRelease(urlRef);
00096 }
00097 }
00098
00099
00100
00101 static void FSRefToLLString(FSRef *fsRef, std::string &llString)
00102 {
00103 OSStatus error = noErr;
00104 char path[MAX_PATH];
00105
00106 error = FSRefMakePath(fsRef, (UInt8*) path, sizeof(path));
00107 if (error == noErr)
00108 llString = path;
00109 }
00110
00111
00112
00113 LLDir_Mac::LLDir_Mac()
00114 {
00115 mDirDelimiter = "/";
00116 mCurrentDirIndex = -1;
00117 mCurrentDirCount = -1;
00118
00119 CFBundleRef mainBundleRef = NULL;
00120 CFURLRef executableURLRef = NULL;
00121 CFStringRef stringRef = NULL;
00122 OSStatus error = noErr;
00123 FSRef fileRef;
00124 CFStringRef secondLifeString = CFSTR("SecondLife");
00125
00126 mainBundleRef = CFBundleGetMainBundle();
00127
00128 executableURLRef = CFBundleCopyExecutableURL(mainBundleRef);
00129
00130 if (executableURLRef != NULL)
00131 {
00132
00133 CFURLRefToLLString(executableURLRef, mExecutablePathAndName, false);
00134
00135
00136 stringRef = CFURLCopyLastPathComponent(executableURLRef);
00137 CFStringRefToLLString(stringRef, mExecutableFilename, true);
00138
00139
00140 CFURLRef executableParentURLRef = CFURLCreateCopyDeletingLastPathComponent(NULL, executableURLRef);
00141 CFURLRefToLLString(executableParentURLRef, mExecutableDir, true);
00142
00143
00144 CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef);
00145 CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true);
00146
00147
00148 error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef);
00149 if (error == noErr)
00150 {
00151 FSRef newFileRef;
00152
00153
00154 error = CFCreateDirectory(&fileRef, secondLifeString, &newFileRef);
00155 if (error == noErr)
00156 {
00157
00158 FSRefToLLString(&newFileRef, mOSUserDir);
00159
00160
00161 (void) CFCreateDirectory(&newFileRef, CFSTR("data"), NULL);
00162 (void) CFCreateDirectory(&newFileRef, CFSTR("cache"), NULL);
00163 (void) CFCreateDirectory(&newFileRef, CFSTR("logs"), NULL);
00164 (void) CFCreateDirectory(&newFileRef, CFSTR("user_settings"), NULL);
00165 (void) CFCreateDirectory(&newFileRef, CFSTR("browser_profile"), NULL);
00166 }
00167 }
00168
00169
00170 mOSUserAppDir = mOSUserDir;
00171
00172
00173 error = FSFindFolder(kOnAppropriateDisk, kTemporaryFolderType, true, &fileRef);
00174 if (error == noErr)
00175 {
00176 FSRef tempRef;
00177 error = CFCreateDirectory(&fileRef, secondLifeString, &tempRef);
00178 if (error == noErr)
00179 FSRefToLLString(&tempRef, mTempDir);
00180 }
00181
00182 mWorkingDir = getCurPath();
00183
00184 CFRelease(executableURLRef);
00185 executableURLRef = NULL;
00186 }
00187 }
00188
00189 LLDir_Mac::~LLDir_Mac()
00190 {
00191 }
00192
00193
00194
00195
00196 void LLDir_Mac::initAppDirs(const std::string &app_name)
00197 {
00198 mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
00199
00200
00201 }
00202
00203 U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &mask)
00204 {
00205 U32 file_count = 0;
00206 glob_t g;
00207
00208 std::string tmp_str;
00209 tmp_str = dirname;
00210 tmp_str += mask;
00211
00212 if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
00213 {
00214 file_count = g.gl_pathc;
00215
00216 globfree(&g);
00217 }
00218
00219 return (file_count);
00220 }
00221
00222
00223
00224 BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
00225 {
00226 glob_t g;
00227 BOOL result = FALSE;
00228 fname = "";
00229
00230 if(!(dirname == mCurrentDir))
00231 {
00232
00233 mCurrentDirIndex = -1;
00234 mCurrentDirCount = -1;
00235 mCurrentDir = dirname;
00236 }
00237
00238 std::string tmp_str;
00239 tmp_str = dirname;
00240 tmp_str += mask;
00241
00242 if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
00243 {
00244 if(g.gl_pathc > 0)
00245 {
00246 if(g.gl_pathc != mCurrentDirCount)
00247 {
00248
00249
00250 mCurrentDirIndex = -1;
00251 mCurrentDirCount = g.gl_pathc;
00252 }
00253
00254 mCurrentDirIndex++;
00255
00256 if((mCurrentDirIndex >= g.gl_pathc) && wrap)
00257 {
00258 mCurrentDirIndex = 0;
00259 }
00260
00261 if(mCurrentDirIndex < g.gl_pathc)
00262 {
00263
00264
00265
00266
00267
00268 char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/');
00269
00270 if(s == NULL)
00271 s = g.gl_pathv[mCurrentDirIndex];
00272 else if(s[0] == '/')
00273 s++;
00274
00275 fname = s;
00276
00277 result = TRUE;
00278 }
00279 }
00280
00281 globfree(&g);
00282 }
00283
00284 return(result);
00285 }
00286
00287
00288 void LLDir_Mac::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
00289 {
00290 S32 which_file;
00291 glob_t g;
00292 fname = "";
00293
00294 std::string tmp_str;
00295 tmp_str = dirname;
00296 tmp_str += mask;
00297
00298 if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
00299 {
00300 if(g.gl_pathc > 0)
00301 {
00302
00303 which_file = ll_rand(g.gl_pathc);
00304
00305
00306
00307
00308
00309 char *s = strrchr(g.gl_pathv[which_file], '/');
00310
00311 if(s == NULL)
00312 s = g.gl_pathv[which_file];
00313 else if(s[0] == '/')
00314 s++;
00315
00316 fname = s;
00317 }
00318
00319 globfree(&g);
00320 }
00321 }
00322
00323 S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask)
00324 {
00325 glob_t g;
00326 S32 result = 0;
00327
00328 std::string tmp_str;
00329 tmp_str = dirname;
00330 tmp_str += mask;
00331
00332 if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
00333 {
00334 int i;
00335
00336 for(i = 0; i < g.gl_pathc; i++)
00337 {
00338
00339
00340 if(unlink(g.gl_pathv[i]) != 0)
00341 {
00342 result = errno;
00343
00344 llwarns << "Problem removing " << g.gl_pathv[i] << " - errorcode: "
00345 << result << llendl;
00346 }
00347 }
00348
00349 globfree(&g);
00350 }
00351
00352 return(result);
00353 }
00354
00355 std::string LLDir_Mac::getCurPath()
00356 {
00357 char tmp_str[LL_MAX_PATH];
00358 getcwd(tmp_str, LL_MAX_PATH);
00359 return tmp_str;
00360 }
00361
00362
00363
00364 BOOL LLDir_Mac::fileExists(const std::string &filename)
00365 {
00366 struct stat stat_data;
00367
00368
00369 int res = stat(filename.c_str(), &stat_data);
00370 if (!res)
00371 {
00372 return TRUE;
00373 }
00374 else
00375 {
00376 return FALSE;
00377 }
00378 }
00379
00380
00381 #endif // LL_DARWIN