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_MOZILLA_PROFILE:
00328 prefix = getOSUserAppDir();
00329 prefix += mDirDelimiter;
00330 prefix += "browser_profile";
00331 break;
00332
00333 default:
00334 llassert(0);
00335 }
00336
00337 std::string filename = in_filename;
00338 if (!subdir.empty())
00339 {
00340 filename = subdir + mDirDelimiter + in_filename;
00341 }
00342 else
00343 {
00344 filename = in_filename;
00345 }
00346
00347 std::string expanded_filename;
00348 if (!filename.empty())
00349 {
00350 if (!prefix.empty())
00351 {
00352 expanded_filename += prefix;
00353 expanded_filename += mDirDelimiter;
00354 expanded_filename += filename;
00355 }
00356 else
00357 {
00358 expanded_filename = filename;
00359 }
00360 }
00361 else if (!prefix.empty())
00362 {
00363
00364 expanded_filename = prefix;
00365 }
00366 else
00367 {
00368 expanded_filename.assign("");
00369 }
00370
00371
00372
00373 return expanded_filename;
00374 }
00375
00376 std::string LLDir::getTempFilename() const
00377 {
00378 LLUUID random_uuid;
00379 char uuid_str[64];
00380
00381 random_uuid.generate();
00382 random_uuid.toString(uuid_str);
00383
00384 std::string temp_filename = getTempDir();
00385 temp_filename += mDirDelimiter;
00386 temp_filename += uuid_str;
00387 temp_filename += ".tmp";
00388
00389 return temp_filename;
00390 }
00391
00392 void LLDir::setLindenUserDir(const std::string &first, const std::string &last)
00393 {
00394
00395 if (!first.empty() && !last.empty())
00396 {
00397
00398
00399 LLString firstlower(first);
00400 LLString::toLower(firstlower);
00401 LLString lastlower(last);
00402 LLString::toLower(lastlower);
00403 mLindenUserDir = getOSUserAppDir();
00404 mLindenUserDir += mDirDelimiter;
00405 mLindenUserDir += firstlower.c_str();
00406 mLindenUserDir += "_";
00407 mLindenUserDir += lastlower.c_str();
00408 }
00409 else
00410 {
00411 llerrs << "Invalid name for LLDir::setLindenUserDir" << llendl;
00412 }
00413
00414 dumpCurrentDirectories();
00415 }
00416
00417 void LLDir::setChatLogsDir(const std::string &path)
00418 {
00419 if (!path.empty() )
00420 {
00421 mChatLogsDir = path;
00422 }
00423 else
00424 {
00425 llwarns << "Invalid name for LLDir::setChatLogsDir" << llendl;
00426 }
00427 }
00428
00429 void LLDir::setPerAccountChatLogsDir(const std::string &first, const std::string &last)
00430 {
00431
00432 if (!first.empty() && !last.empty())
00433 {
00434
00435
00436 LLString firstlower(first);
00437 LLString::toLower(firstlower);
00438 LLString lastlower(last);
00439 LLString::toLower(lastlower);
00440 mPerAccountChatLogsDir = getChatLogsDir();
00441 mPerAccountChatLogsDir += mDirDelimiter;
00442 mPerAccountChatLogsDir += firstlower.c_str();
00443 mPerAccountChatLogsDir += "_";
00444 mPerAccountChatLogsDir += lastlower.c_str();
00445 }
00446 else
00447 {
00448 llwarns << "Invalid name for LLDir::setPerAccountChatLogsDir" << llendl;
00449 }
00450 }
00451
00452 void LLDir::setSkinFolder(const std::string &skin_folder)
00453 {
00454 mSkinDir = getAppRODataDir();
00455 mSkinDir += mDirDelimiter;
00456 mSkinDir += "skins";
00457 mSkinDir += mDirDelimiter;
00458 mSkinDir += skin_folder;
00459 }
00460
00461 bool LLDir::setCacheDir(const std::string &path)
00462 {
00463 if (path.empty() )
00464 {
00465
00466 mCacheDir = "";
00467 return true;
00468 }
00469 else
00470 {
00471 LLFile::mkdir(path.c_str());
00472 std::string tempname = path + mDirDelimiter + "temp";
00473 LLFILE* file = LLFile::fopen(tempname.c_str(),"wt");
00474 if (file)
00475 {
00476 fclose(file);
00477 LLFile::remove(tempname.c_str());
00478 mCacheDir = path;
00479 return true;
00480 }
00481 return false;
00482 }
00483 }
00484
00485 void LLDir::dumpCurrentDirectories()
00486 {
00487 llinfos << "Current Directories:" << llendl;
00488
00489 llinfos << " CurPath: " << getCurPath() << llendl;
00490 llinfos << " AppName: " << getAppName() << llendl;
00491 llinfos << " ExecutableFilename: " << getExecutableFilename() << llendl;
00492 llinfos << " ExecutableDir: " << getExecutableDir() << llendl;
00493 llinfos << " ExecutablePathAndName: " << getExecutablePathAndName() << llendl;
00494 llinfos << " WorkingDir: " << getWorkingDir() << llendl;
00495 llinfos << " AppRODataDir: " << getAppRODataDir() << llendl;
00496 llinfos << " OSUserDir: " << getOSUserDir() << llendl;
00497 llinfos << " OSUserAppDir: " << getOSUserAppDir() << llendl;
00498 llinfos << " LindenUserDir: " << getLindenUserDir() << llendl;
00499 llinfos << " TempDir: " << getTempDir() << llendl;
00500 llinfos << " CAFile: " << getCAFile() << llendl;
00501 llinfos << " SkinDir: " << getSkinDir() << llendl;
00502 }
00503
00504
00505 void dir_exists_or_crash(const std::string &dir_name)
00506 {
00507 #if LL_WINDOWS
00508
00509
00510 LLFile::mkdir(dir_name.c_str(), 0700);
00511 #else
00512 struct stat dir_stat;
00513 if(0 != LLFile::stat(dir_name.c_str(), &dir_stat))
00514 {
00515 S32 stat_rv = errno;
00516 if(ENOENT == stat_rv)
00517 {
00518 if(0 != LLFile::mkdir(dir_name.c_str(), 0700))
00519 {
00520 llerrs << "Unable to create directory: " << dir_name << llendl;
00521 }
00522 }
00523 else
00524 {
00525 llerrs << "Unable to stat: " << dir_name << " errno = " << stat_rv
00526 << llendl;
00527 }
00528 }
00529 else
00530 {
00531
00532 if(!S_ISDIR(dir_stat.st_mode))
00533 {
00534 llerrs << "Data directory collision: " << dir_name << llendl;
00535 }
00536 }
00537 #endif
00538 }