lldir_mac.cpp

Go to the documentation of this file.
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                 // mExecutablePathAndName
00133                 CFURLRefToLLString(executableURLRef, mExecutablePathAndName, false);
00134                 
00135                 // mExecutableFilename
00136                 stringRef = CFURLCopyLastPathComponent(executableURLRef);
00137                 CFStringRefToLLString(stringRef, mExecutableFilename, true);
00138                 
00139                 // mExecutableDir
00140                 CFURLRef        executableParentURLRef = CFURLCreateCopyDeletingLastPathComponent(NULL, executableURLRef);
00141                 CFURLRefToLLString(executableParentURLRef, mExecutableDir, true);
00142                 
00143                 // mAppRODataDir
00144                 CFURLRef        resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef);
00145                 CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true);
00146                 
00147                 // mOSUserDir
00148                 error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef);
00149                 if (error == noErr)
00150                 {
00151                         FSRef   newFileRef;
00152                         
00153                         // Create the directory
00154                         error = CFCreateDirectory(&fileRef, secondLifeString, &newFileRef);
00155                         if (error == noErr)
00156                         {
00157                                 // Save the full path to the folder
00158                                 FSRefToLLString(&newFileRef, mOSUserDir);
00159                                 
00160                                 // Create our sub-dirs
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                 // mOSUserAppDir
00170                 mOSUserAppDir = mOSUserDir;
00171                 
00172                 // mTempDir
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 // Implementation
00194 
00195 
00196 void LLDir_Mac::initAppDirs(const std::string &app_name)
00197 {
00198         mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
00199 
00200         //dumpCurrentDirectories();
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 // get the next file in the directory
00223 // automatically wrap if we've hit the end
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                 // different dir specified, close old search
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                                 // Number of matches has changed since the last search, meaning a file has been added or deleted.
00249                                 // Reset the index.
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 //                              llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
00264 
00265                                 // The API wants just the filename, not the full path.
00266                                 //fname = g.gl_pathv[mCurrentDirIndex];
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 // get a random file in the directory
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 //                      llinfos << "getRandomFileInDir: returning number " << which_file << ", path is " << g.gl_pathv[which_file] << llendl;
00306                         // The API wants just the filename, not the full path.
00307                         //fname = g.gl_pathv[which_file];
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 //                      llinfos << "deleteFilesInDir: deleting number " << i << ", path is " << g.gl_pathv[i] << llendl;
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];      /* Flawfinder: ignore */ 
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         // Check the age of the file
00368         // Now, we see if the files we've gathered are recent...
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

Generated on Thu Jul 1 06:08:24 2010 for Second Life Viewer by  doxygen 1.4.7