lldir_mac.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:11k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lldir_mac.cpp
  3.  * @brief Implementation of directory utilities for Mac OS X
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #if LL_DARWIN
  33. #include "linden_common.h"
  34. #include "lldir_mac.h"
  35. #include "llerror.h"
  36. #include "llrand.h"
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <unistd.h>
  40. #include <glob.h>
  41. #include <Carbon/Carbon.h>
  42. // --------------------------------------------------------------------------------
  43. static OSStatus CFCreateDirectory(FSRef *parentRef, CFStringRef name, FSRef *newRef)
  44. {
  45. OSStatus result = noErr;
  46. HFSUniStr255 uniStr;
  47. uniStr.length = CFStringGetLength(name);
  48. CFStringGetCharacters(name, CFRangeMake(0, uniStr.length), uniStr.unicode);
  49. result = FSMakeFSRefUnicode(parentRef, uniStr.length, uniStr.unicode, kTextEncodingMacRoman, newRef);
  50. if (result != noErr)
  51. {
  52. result = FSCreateDirectoryUnicode(parentRef, uniStr.length, uniStr.unicode, 0, NULL, newRef, NULL, NULL);
  53. }
  54. return result;
  55. }
  56. // --------------------------------------------------------------------------------
  57. static void CFStringRefToLLString(CFStringRef stringRef, std::string &llString, bool releaseWhenDone)
  58. {
  59. if (stringRef)
  60. {
  61. long stringSize = CFStringGetLength(stringRef) + 1;
  62. long bufferSize = CFStringGetMaximumSizeForEncoding(stringSize,kCFStringEncodingUTF8);
  63. char* buffer = new char[bufferSize];
  64. memset(buffer, 0, bufferSize);
  65. if (CFStringGetCString(stringRef, buffer, bufferSize, kCFStringEncodingUTF8))
  66. llString = buffer;
  67. delete[] buffer;
  68. if (releaseWhenDone)
  69. CFRelease(stringRef);
  70. }
  71. }
  72. // --------------------------------------------------------------------------------
  73. static void CFURLRefToLLString(CFURLRef urlRef, std::string &llString, bool releaseWhenDone)
  74. {
  75. if (urlRef)
  76. {
  77. CFURLRef absoluteURLRef = CFURLCopyAbsoluteURL(urlRef);
  78. if (absoluteURLRef)
  79. {
  80. CFStringRef stringRef = CFURLCopyFileSystemPath(absoluteURLRef, kCFURLPOSIXPathStyle);
  81. CFStringRefToLLString(stringRef, llString, true);
  82. CFRelease(absoluteURLRef);
  83. }
  84. if (releaseWhenDone)
  85. CFRelease(urlRef);
  86. }
  87. }
  88. // --------------------------------------------------------------------------------
  89. static void FSRefToLLString(FSRef *fsRef, std::string &llString)
  90. {
  91. OSStatus error = noErr;
  92. char path[MAX_PATH];
  93. error = FSRefMakePath(fsRef, (UInt8*) path, sizeof(path));
  94. if (error == noErr)
  95. llString = path;
  96. }
  97. // --------------------------------------------------------------------------------
  98. LLDir_Mac::LLDir_Mac()
  99. {
  100. mDirDelimiter = "/";
  101. mCurrentDirIndex = -1;
  102. mCurrentDirCount = -1;
  103. CFBundleRef mainBundleRef = NULL;
  104. CFURLRef executableURLRef = NULL;
  105. CFStringRef stringRef = NULL;
  106. OSStatus error = noErr;
  107. FSRef fileRef;
  108. CFStringRef secondLifeString = CFSTR("SecondLife");
  109. mainBundleRef = CFBundleGetMainBundle();
  110. executableURLRef = CFBundleCopyExecutableURL(mainBundleRef);
  111. if (executableURLRef != NULL)
  112. {
  113. // mExecutablePathAndName
  114. CFURLRefToLLString(executableURLRef, mExecutablePathAndName, false);
  115. // mExecutableFilename
  116. stringRef = CFURLCopyLastPathComponent(executableURLRef);
  117. CFStringRefToLLString(stringRef, mExecutableFilename, true);
  118. // mExecutableDir
  119. CFURLRef executableParentURLRef = CFURLCreateCopyDeletingLastPathComponent(NULL, executableURLRef);
  120. CFURLRefToLLString(executableParentURLRef, mExecutableDir, true);
  121. // mAppRODataDir
  122. // *NOTE: When running in a dev tree, use the copy of
  123. // skins in indra/newview/ rather than in the application bundle.  This
  124. // mirrors Windows dev environment behavior and allows direct checkin
  125. // of edited skins/xui files. JC
  126. // MBW -- This keeps the mac application from finding other things.
  127. // If this is really for skins, it should JUST apply to skins.
  128. CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef);
  129. CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true);
  130. U32 indra_pos = mExecutableDir.find("/indra");
  131. if (indra_pos != std::string::npos)
  132. {
  133. // ...we're in a dev checkout
  134. mSkinBaseDir = mExecutableDir.substr(0, indra_pos)
  135. + "/indra/newview/skins";
  136. llinfos << "Running in dev checkout with mSkinBaseDir "
  137. << mSkinBaseDir << llendl;
  138. }
  139. else
  140. {
  141. // ...normal installation running
  142. mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
  143. }
  144. // mOSUserDir
  145. error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef);
  146. if (error == noErr)
  147. {
  148. FSRef newFileRef;
  149. // Create the directory
  150. error = CFCreateDirectory(&fileRef, secondLifeString, &newFileRef);
  151. if (error == noErr)
  152. {
  153. // Save the full path to the folder
  154. FSRefToLLString(&newFileRef, mOSUserDir);
  155. // Create our sub-dirs
  156. (void) CFCreateDirectory(&newFileRef, CFSTR("data"), NULL);
  157. //(void) CFCreateDirectory(&newFileRef, CFSTR("cache"), NULL);
  158. (void) CFCreateDirectory(&newFileRef, CFSTR("logs"), NULL);
  159. (void) CFCreateDirectory(&newFileRef, CFSTR("user_settings"), NULL);
  160. (void) CFCreateDirectory(&newFileRef, CFSTR("browser_profile"), NULL);
  161. }
  162. }
  163. //mOSCacheDir
  164. FSRef cacheDirRef;
  165. error = FSFindFolder(kUserDomain, kCachedDataFolderType, true, &cacheDirRef);
  166. if (error == noErr)
  167. {
  168. FSRefToLLString(&cacheDirRef, mOSCacheDir);
  169. (void)CFCreateDirectory(&cacheDirRef, CFSTR("SecondLife"),NULL);
  170. }
  171. // mOSUserAppDir
  172. mOSUserAppDir = mOSUserDir;
  173. // mTempDir
  174. error = FSFindFolder(kOnAppropriateDisk, kTemporaryFolderType, true, &fileRef);
  175. if (error == noErr)
  176. {
  177. FSRef tempRef;
  178. error = CFCreateDirectory(&fileRef, secondLifeString, &tempRef);
  179. if (error == noErr)
  180. FSRefToLLString(&tempRef, mTempDir);
  181. }
  182. mWorkingDir = getCurPath();
  183. mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin";
  184. CFRelease(executableURLRef);
  185. executableURLRef = NULL;
  186. }
  187. }
  188. LLDir_Mac::~LLDir_Mac()
  189. {
  190. }
  191. // Implementation
  192. void LLDir_Mac::initAppDirs(const std::string &app_name,
  193. const std::string& app_read_only_data_dir)
  194. {
  195. // Allow override so test apps can read newview directory
  196. if (!app_read_only_data_dir.empty())
  197. {
  198. mAppRODataDir = app_read_only_data_dir;
  199. mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
  200. }
  201. mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
  202. //dumpCurrentDirectories();
  203. }
  204. U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &mask)
  205. {
  206. U32 file_count = 0;
  207. glob_t g;
  208. std::string tmp_str;
  209. tmp_str = dirname;
  210. tmp_str += mask;
  211. if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
  212. {
  213. file_count = g.gl_pathc;
  214. globfree(&g);
  215. }
  216. return (file_count);
  217. }
  218. // get the next file in the directory
  219. // automatically wrap if we've hit the end
  220. BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
  221. {
  222. glob_t g;
  223. BOOL result = FALSE;
  224. fname = "";
  225. if(!(dirname == mCurrentDir))
  226. {
  227. // different dir specified, close old search
  228. mCurrentDirIndex = -1;
  229. mCurrentDirCount = -1;
  230. mCurrentDir = dirname;
  231. }
  232. std::string tmp_str;
  233. tmp_str = dirname;
  234. tmp_str += mask;
  235. if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
  236. {
  237. if(g.gl_pathc > 0)
  238. {
  239. if(g.gl_pathc != mCurrentDirCount)
  240. {
  241. // Number of matches has changed since the last search, meaning a file has been added or deleted.
  242. // Reset the index.
  243. mCurrentDirIndex = -1;
  244. mCurrentDirCount = g.gl_pathc;
  245. }
  246. mCurrentDirIndex++;
  247. if((mCurrentDirIndex >= g.gl_pathc) && wrap)
  248. {
  249. mCurrentDirIndex = 0;
  250. }
  251. if(mCurrentDirIndex < g.gl_pathc)
  252. {
  253. // llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
  254. // The API wants just the filename, not the full path.
  255. //fname = g.gl_pathv[mCurrentDirIndex];
  256. char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/');
  257. if(s == NULL)
  258. s = g.gl_pathv[mCurrentDirIndex];
  259. else if(s[0] == '/')
  260. s++;
  261. fname = s;
  262. result = TRUE;
  263. }
  264. }
  265. globfree(&g);
  266. }
  267. return(result);
  268. }
  269. // get a random file in the directory
  270. void LLDir_Mac::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
  271. {
  272. S32 which_file;
  273. glob_t g;
  274. fname = "";
  275. std::string tmp_str;
  276. tmp_str = dirname;
  277. tmp_str += mask;
  278. if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
  279. {
  280. if(g.gl_pathc > 0)
  281. {
  282. which_file = ll_rand(g.gl_pathc);
  283. // llinfos << "getRandomFileInDir: returning number " << which_file << ", path is " << g.gl_pathv[which_file] << llendl;
  284. // The API wants just the filename, not the full path.
  285. //fname = g.gl_pathv[which_file];
  286. char *s = strrchr(g.gl_pathv[which_file], '/');
  287. if(s == NULL)
  288. s = g.gl_pathv[which_file];
  289. else if(s[0] == '/')
  290. s++;
  291. fname = s;
  292. }
  293. globfree(&g);
  294. }
  295. }
  296. S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask)
  297. {
  298. glob_t g;
  299. S32 result = 0;
  300. std::string tmp_str;
  301. tmp_str = dirname;
  302. tmp_str += mask;
  303. if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
  304. {
  305. int i;
  306. for(i = 0; i < g.gl_pathc; i++)
  307. {
  308. // llinfos << "deleteFilesInDir: deleting number " << i << ", path is " << g.gl_pathv[i] << llendl;
  309. if(unlink(g.gl_pathv[i]) != 0)
  310. {
  311. result = errno;
  312. llwarns << "Problem removing " << g.gl_pathv[i] << " - errorcode: "
  313. << result << llendl;
  314. }
  315. }
  316. globfree(&g);
  317. }
  318. return(result);
  319. }
  320. std::string LLDir_Mac::getCurPath()
  321. {
  322. char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ 
  323. getcwd(tmp_str, LL_MAX_PATH);
  324. return tmp_str;
  325. }
  326. BOOL LLDir_Mac::fileExists(const std::string &filename) const
  327. {
  328. struct stat stat_data;
  329. // Check the age of the file
  330. // Now, we see if the files we've gathered are recent...
  331. int res = stat(filename.c_str(), &stat_data);
  332. if (!res)
  333. {
  334. return TRUE;
  335. }
  336. else
  337. {
  338. return FALSE;
  339. }
  340. }
  341. /*virtual*/ std::string LLDir_Mac::getLLPluginLauncher()
  342. {
  343. return gDirUtilp->getAppRODataDir() + gDirUtilp->getDirDelimiter() +
  344. "SLPlugin";
  345. }
  346. /*virtual*/ std::string LLDir_Mac::getLLPluginFilename(std::string base_name)
  347. {
  348. return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() +
  349. base_name + ".dylib";
  350. }
  351. #endif // LL_DARWIN