00001
00032 #include "linden_common.h"
00033
00034 #if !LL_WINDOWS
00035 #include <sys/stat.h>
00036 #include <sys/types.h>
00037 #include <errno.h>
00038 #else
00039 #include <direct.h>
00040 #endif
00041
00042 #include "lldir.h"
00043 #include "llerror.h"
00044 #include "lluuid.h"
00045
00046 #if LL_WINDOWS
00047 #include "lldir_win32.h"
00048 LLDir_Win32 gDirUtil;
00049 #elif LL_DARWIN
00050 #include "lldir_mac.h"
00051 LLDir_Mac gDirUtil;
00052 #elif LL_SOLARIS
00053 #include "lldir_solaris.h"
00054 LLDir_Solaris gDirUtil;
00055 #else
00056 #include "lldir_linux.h"
00057 LLDir_Linux gDirUtil;
00058 #endif
00059
00060 LLDir *gDirUtilp = (LLDir *)&gDirUtil;
00061
00062 LLDir::LLDir()
00063 : mAppName(""),
00064 mExecutablePathAndName(""),
00065 mExecutableFilename(""),
00066 mExecutableDir(""),
00067 mAppRODataDir(""),
00068 mOSUserDir(""),
00069 mOSUserAppDir(""),
00070 mLindenUserDir(""),
00071 mCAFile(""),
00072 mTempDir(""),
00073 mDirDelimiter("")
00074 {
00075 }
00076
00077 LLDir::~LLDir()
00078 {
00079 }
00080
00081
00082 S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
00083 {
00084 S32 count = 0;
00085 std::string filename;
00086 std::string fullpath;
00087 S32 result;
00088 while (getNextFileInDir(dirname, mask, filename, FALSE))
00089 {
00090 if ((filename == ".") || (filename == ".."))
00091 {
00092
00093 count++;
00094 continue;
00095 }
00096 fullpath = dirname;
00097 fullpath += getDirDelimiter();
00098 fullpath += filename;
00099
00100 S32 retry_count = 0;
00101 while (retry_count < 5)
00102 {
00103 if (0 != LLFile::remove(fullpath.c_str()))
00104 {
00105 result = errno;
00106 llwarns << "Problem removing " << fullpath << " - errorcode: "
00107 << result << " attempt " << retry_count << llendl;
00108 ms_sleep(1000);
00109 }
00110 else
00111 {
00112 if (retry_count)
00113 {
00114 llwarns << "Successfully removed " << fullpath << llendl;
00115 }
00116 break;
00117 }
00118 retry_count++;
00119 }
00120 count++;
00121 }
00122 return count;
00123 }
00124
00125 const std::string LLDir::findFile(const std::string &filename,
00126 const std::string searchPath1,
00127 const std::string searchPath2,
00128 const std::string searchPath3)
00129 {
00130 std::vector<std::string> search_paths;
00131 search_paths.push_back(searchPath1);
00132 search_paths.push_back(searchPath2);
00133 search_paths.push_back(searchPath3);
00134
00135 std::vector<std::string>::iterator search_path_iter;
00136 for (search_path_iter = search_paths.begin();
00137 search_path_iter != search_paths.end();
00138 ++search_path_iter)
00139 {
00140 if (!search_path_iter->empty())
00141 {
00142 std::string filename_and_path = (*search_path_iter) + getDirDelimiter() + filename;
00143 if (fileExists(filename_and_path))
00144 {
00145 return filename_and_path;
00146 }
00147 }
00148 }
00149 return "";
00150 }
00151
00152
00153 const std::string &LLDir::getExecutablePathAndName() const
00154 {
00155 return mExecutablePathAndName;
00156 }
00157
00158 const std::string &LLDir::getExecutableFilename() const
00159 {
00160 return mExecutableFilename;
00161 }
00162
00163 const std::string &LLDir::getExecutableDir() const
00164 {
00165 return mExecutableDir;
00166 }
00167
00168 const std::string &LLDir::getWorkingDir() const
00169 {
00170 return mWorkingDir;
00171 }
00172
00173 const std::string &LLDir::getAppName() const
00174 {
00175 return mAppName;
00176 }
00177
00178 const std::string &LLDir::getAppRODataDir() const
00179 {
00180 return mAppRODataDir;
00181 }
00182
00183 const std::string &LLDir::getOSUserDir() const
00184 {
00185 return mOSUserDir;
00186 }
00187
00188 const std::string &LLDir::getOSUserAppDir() const
00189 {
00190 return mOSUserAppDir;
00191 }
00192
00193 const std::string &LLDir::getLindenUserDir() const
00194 {
00195 return mLindenUserDir;
00196 }
00197
00198 const std::string &LLDir::getChatLogsDir() const
00199 {
00200 return mChatLogsDir;
00201 }
00202
00203 const std::string &LLDir::getPerAccountChatLogsDir() const
00204 {
00205 return mPerAccountChatLogsDir;
00206 }
00207
00208 const std::string &LLDir::getTempDir() const
00209 {
00210 return mTempDir;
00211 }
00212
00213 const std::string LLDir::getCacheDir(bool get_default) const
00214 {
00215 if (mCacheDir.empty() || get_default)
00216 {
00217 std::string res;
00218 if (getOSUserAppDir().empty())
00219 {
00220 res = "data";
00221 }
00222 else
00223 {
00224 res = getOSUserAppDir() + mDirDelimiter + "cache";
00225 }
00226 return res;
00227 }
00228 else
00229 {
00230 return mCacheDir;
00231 }
00232 }
00233
00234 const std::string &LLDir::getCAFile() const
00235 {
00236 return mCAFile;
00237 }
00238
00239 const std::string &LLDir::getDirDelimiter() const
00240 {
00241 return mDirDelimiter;
00242 }
00243
00244 const std::string &LLDir::getSkinDir() const
00245 {
00246 return mSkinDir;
00247 }
00248
00249 std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const
00250 {
00251 return getExpandedFilename(location, "", filename);
00252 }
00253
00254 std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir, const std::string& in_filename) const
00255 {
00256 std::string prefix;
00257 switch (location)
00258 {
00259 case LL_PATH_NONE:
00260
00261 break;
00262
00263 case LL_PATH_APP_SETTINGS:
00264 prefix = getAppRODataDir();
00265 prefix += mDirDelimiter;
00266 prefix += "app_settings";
00267 break;
00268
00269 case LL_PATH_CHARACTER:
00270 prefix = getAppRODataDir();
00271 prefix += mDirDelimiter;
00272 prefix += "character";
00273 break;
00274
00275 case LL_PATH_MOTIONS:
00276 prefix = getAppRODataDir();
00277 prefix += mDirDelimiter;
00278 prefix += "motions";
00279 break;
00280
00281 case LL_PATH_HELP:
00282 prefix = "help";
00283 break;
00284
00285 case LL_PATH_CACHE:
00286 prefix = getCacheDir();
00287 break;
00288
00289 case LL_PATH_USER_SETTINGS:
00290 prefix = getOSUserAppDir();
00291 prefix += mDirDelimiter;
00292 prefix += "user_settings";
00293 break;
00294
00295 case LL_PATH_PER_SL_ACCOUNT:
00296 prefix = getLindenUserDir();
00297 break;
00298
00299 case LL_PATH_CHAT_LOGS:
00300 prefix = getChatLogsDir();
00301 break;
00302
00303 case LL_PATH_PER_ACCOUNT_CHAT_LOGS:
00304 prefix = getPerAccountChatLogsDir();
00305 break;
00306
00307 case LL_PATH_LOGS:
00308 prefix = getOSUserAppDir();
00309 prefix += mDirDelimiter;
00310 prefix += "logs";
00311 break;
00312
00313 case LL_PATH_TEMP:
00314 prefix = getTempDir();
00315 break;
00316
00317 case LL_PATH_TOP_SKIN:
00318 prefix = getSkinDir();
00319 break;
00320
00321 case LL_PATH_SKINS:
00322 prefix = getAppRODataDir();
00323 prefix += mDirDelimiter;
00324 prefix += "skins";
00325 break;
00326
00327 case LL_PATH_HTML:
00328 prefix = getAppRODataDir();
00329 prefix += mDirDelimiter;
00330 prefix += "skins";
00331 prefix += mDirDelimiter;
00332 prefix += "html";
00333 break;
00334
00335 case LL_PATH_MOZILLA_PROFILE:
00336 prefix = getOSUserAppDir();
00337 prefix += mDirDelimiter;
00338 prefix += "browser_profile";
00339 break;
00340
00341 default:
00342 llassert(0);
00343 }
00344
00345 std::string filename = in_filename;
00346 if (!subdir.empty())
00347 {
00348 filename = subdir + mDirDelimiter + in_filename;
00349 }
00350 else
00351 {
00352 filename = in_filename;
00353 }
00354
00355 std::string expanded_filename;
00356 if (!filename.empty())
00357 {
00358 if (!prefix.empty())
00359 {
00360 expanded_filename += prefix;
00361 expanded_filename += mDirDelimiter;
00362 expanded_filename += filename;
00363 }
00364 else
00365 {
00366 expanded_filename = filename;
00367 }
00368 }
00369 else if (!prefix.empty())
00370 {
00371
00372 expanded_filename = prefix;
00373 }
00374 else
00375 {
00376 expanded_filename.assign("");
00377 }
00378
00379
00380
00381 return expanded_filename;
00382 }
00383
00384 std::string LLDir::getTempFilename() const
00385 {
00386 LLUUID random_uuid;
00387 char uuid_str[64];
00388
00389 random_uuid.generate();
00390 random_uuid.toString(uuid_str);
00391
00392 std::string temp_filename = getTempDir();
00393 temp_filename += mDirDelimiter;
00394 temp_filename += uuid_str;
00395 temp_filename += ".tmp";
00396
00397 return temp_filename;
00398 }
00399
00400 void LLDir::setLindenUserDir(const std::string &first, const std::string &last)
00401 {
00402
00403 if (!first.empty() && !last.empty())
00404 {
00405
00406
00407 LLString firstlower(first);
00408 LLString::toLower(firstlower);
00409 LLString lastlower(last);
00410 LLString::toLower(lastlower);
00411 mLindenUserDir = getOSUserAppDir();
00412 mLindenUserDir += mDirDelimiter;
00413 mLindenUserDir += firstlower.c_str();
00414 mLindenUserDir += "_";
00415 mLindenUserDir += lastlower.c_str();
00416 }
00417 else
00418 {
00419 llerrs << "Invalid name for LLDir::setLindenUserDir" << llendl;
00420 }
00421
00422 dumpCurrentDirectories();
00423 }
00424
00425 void LLDir::setChatLogsDir(const std::string &path)
00426 {
00427 if (!path.empty() )
00428 {
00429 mChatLogsDir = path;
00430 }
00431 else
00432 {
00433 llwarns << "Invalid name for LLDir::setChatLogsDir" << llendl;
00434 }
00435 }
00436
00437 void LLDir::setPerAccountChatLogsDir(const std::string &first, const std::string &last)
00438 {
00439
00440 if (!first.empty() && !last.empty())
00441 {
00442
00443
00444 LLString firstlower(first);
00445 LLString::toLower(firstlower);
00446 LLString lastlower(last);
00447 LLString::toLower(lastlower);
00448 mPerAccountChatLogsDir = getChatLogsDir();
00449 mPerAccountChatLogsDir += mDirDelimiter;
00450 mPerAccountChatLogsDir += firstlower.c_str();
00451 mPerAccountChatLogsDir += "_";
00452 mPerAccountChatLogsDir += lastlower.c_str();
00453 }
00454 else
00455 {
00456 llwarns << "Invalid name for LLDir::setPerAccountChatLogsDir" << llendl;
00457 }
00458 }
00459
00460 void LLDir::setSkinFolder(const std::string &skin_folder)
00461 {
00462 mSkinDir = getAppRODataDir();
00463 mSkinDir += mDirDelimiter;
00464 mSkinDir += "skins";
00465 mSkinDir += mDirDelimiter;
00466 mSkinDir += skin_folder;
00467 }
00468
00469 bool LLDir::setCacheDir(const std::string &path)
00470 {
00471 if (path.empty() )
00472 {
00473
00474 mCacheDir = "";
00475 return true;
00476 }
00477 else
00478 {
00479 LLFile::mkdir(path.c_str());
00480 std::string tempname = path + mDirDelimiter + "temp";
00481 LLFILE* file = LLFile::fopen(tempname.c_str(),"wt");
00482 if (file)
00483 {
00484 fclose(file);
00485 LLFile::remove(tempname.c_str());
00486 mCacheDir = path;
00487 return true;
00488 }
00489 return false;
00490 }
00491 }
00492
00493 void LLDir::dumpCurrentDirectories()
00494 {
00495 LL_DEBUGS2("AppInit","Directories") << "Current Directories:" << LL_ENDL;
00496
00497 LL_DEBUGS2("AppInit","Directories") << " CurPath: " << getCurPath() << LL_ENDL;
00498 LL_DEBUGS2("AppInit","Directories") << " AppName: " << getAppName() << LL_ENDL;
00499 LL_DEBUGS2("AppInit","Directories") << " ExecutableFilename: " << getExecutableFilename() << LL_ENDL;
00500 LL_DEBUGS2("AppInit","Directories") << " ExecutableDir: " << getExecutableDir() << LL_ENDL;
00501 LL_DEBUGS2("AppInit","Directories") << " ExecutablePathAndName: " << getExecutablePathAndName() << LL_ENDL;
00502 LL_DEBUGS2("AppInit","Directories") << " WorkingDir: " << getWorkingDir() << LL_ENDL;
00503 LL_DEBUGS2("AppInit","Directories") << " AppRODataDir: " << getAppRODataDir() << LL_ENDL;
00504 LL_DEBUGS2("AppInit","Directories") << " OSUserDir: " << getOSUserDir() << LL_ENDL;
00505 LL_DEBUGS2("AppInit","Directories") << " OSUserAppDir: " << getOSUserAppDir() << LL_ENDL;
00506 LL_DEBUGS2("AppInit","Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL;
00507 LL_DEBUGS2("AppInit","Directories") << " TempDir: " << getTempDir() << LL_ENDL;
00508 LL_DEBUGS2("AppInit","Directories") << " CAFile: " << getCAFile() << LL_ENDL;
00509 LL_DEBUGS2("AppInit","Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
00510 }
00511
00512
00513 void dir_exists_or_crash(const std::string &dir_name)
00514 {
00515 #if LL_WINDOWS
00516
00517
00518 LLFile::mkdir(dir_name.c_str(), 0700);
00519 #else
00520 struct stat dir_stat;
00521 if(0 != LLFile::stat(dir_name.c_str(), &dir_stat))
00522 {
00523 S32 stat_rv = errno;
00524 if(ENOENT == stat_rv)
00525 {
00526 if(0 != LLFile::mkdir(dir_name.c_str(), 0700))
00527 {
00528 llerrs << "Unable to create directory: " << dir_name << llendl;
00529 }
00530 }
00531 else
00532 {
00533 llerrs << "Unable to stat: " << dir_name << " errno = " << stat_rv
00534 << llendl;
00535 }
00536 }
00537 else
00538 {
00539
00540 if(!S_ISDIR(dir_stat.st_mode))
00541 {
00542 llerrs << "Data directory collision: " << dir_name << llendl;
00543 }
00544 }
00545 #endif
00546 }