lldir_linux.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /**
  2. * @file lldir_linux.cpp
  3. * @brief Implementation of Linux-specific directory related methods
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2002-2009, 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. #include "linden_common.h"
  33. #include <dirent.h>
  34. #include <errno.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37. #include <unistd.h>
  38. #include <pwd.h>
  39. #include "lldir.h"
  40. static std::string get_current_user_home(char* fallback)
  41. {
  42. const uid_t uid = getuid();
  43. struct passwd* pw;
  44. char* result_cstr = fallback;
  45. pw = getpwuid(uid);
  46. if (pw && pw->pw_dir)
  47. {
  48. result_cstr = (char*)pw->pw_dir;
  49. }
  50. else
  51. {
  52. llinfos << "Could not detect home directory from passwd - trying $HOME"
  53. << llendl;
  54. const char* const home_env = getenv("HOME");
  55. if (home_env)
  56. {
  57. result_cstr = (char*)home_env;
  58. }
  59. else
  60. {
  61. llwarns << "Could not detect home directory ! Falling back to: "
  62. << fallback << llendl;
  63. }
  64. }
  65. return std::string(result_cstr);
  66. }
  67. void LLDir::init()
  68. {
  69. char* env = getenv("TMP");
  70. if (!env)
  71. {
  72. env = getenv("TMPDIR");
  73. }
  74. if (env)
  75. {
  76. mTempDir.assign(env);
  77. size_t length = mTempDir.length();
  78. if (length && mTempDir[length - 1] == '/')
  79. {
  80. mTempDir = mTempDir.substr(0, length - 1);
  81. }
  82. }
  83. if (mTempDir.empty())
  84. {
  85. mTempDir = "/tmp";
  86. }
  87. char tmp_str[LL_MAX_PATH];
  88. if (getcwd(tmp_str, LL_MAX_PATH) == NULL)
  89. {
  90. strncpy(tmp_str, mTempDir.c_str(), LL_MAX_PATH - 1);
  91. tmp_str[LL_MAX_PATH - 1] = '\0';
  92. llwarns << "Could not get current directory; changing to " << tmp_str
  93. << llendl;
  94. if (chdir(tmp_str) == -1)
  95. {
  96. llerrs << "Could not change directory to " << tmp_str << llendl;
  97. }
  98. }
  99. mExecutableFilename.clear();
  100. mExecutablePathAndName.clear();
  101. mExecutableDir = tmp_str;
  102. mWorkingDir = tmp_str;
  103. mAppRODataDir = tmp_str;
  104. mOSUserDir = get_current_user_home(tmp_str);
  105. mOSUserAppDir.clear();
  106. char path[32];
  107. // *NOTE: /proc/%d/exe would not work on FreeBSD, but this is the
  108. // Linux implementation, and it works this way.
  109. snprintf(path, sizeof(path), "/proc/%d/exe", (int)getpid());
  110. int rc = readlink(path, tmp_str, sizeof(tmp_str) - 1);
  111. if (rc != -1 && rc <= (int)sizeof(tmp_str) - 1)
  112. {
  113. tmp_str[rc] = '\0'; // readlink() does not 0-terminate the buffer
  114. mExecutablePathAndName = tmp_str;
  115. char* path_end;
  116. if ((path_end = strrchr(tmp_str,'/')))
  117. {
  118. *path_end = '\0';
  119. mExecutableDir = tmp_str;
  120. mWorkingDir = tmp_str;
  121. mExecutableFilename = path_end + 1;
  122. }
  123. else
  124. {
  125. mExecutableFilename = tmp_str;
  126. }
  127. }
  128. mLLPluginDir = mExecutableDir + "/llplugin";
  129. dumpCurrentDirectories();
  130. }
  131. void LLDir::initAppDirs(const std::string& app_name)
  132. {
  133. mAppName = app_name;
  134. std::string upper_app_name(app_name);
  135. LLStringUtil::toUpper(upper_app_name);
  136. char* app_home_env = getenv((upper_app_name + "_USER_DIR").c_str());
  137. if (app_home_env)
  138. {
  139. // User has specified own userappdir i.e. $SECONDLIFE_USER_DIR
  140. mOSUserAppDir = app_home_env;
  141. }
  142. else
  143. {
  144. // Traditionally on unixoids, MyApp gets ~/.myapp dir for data
  145. std::string lower_app_name(app_name);
  146. LLStringUtil::toLower(lower_app_name);
  147. mOSUserAppDir = mOSUserDir + "/." + lower_app_name;
  148. }
  149. // Create any directories we expect to write to.
  150. if (!LLFile::mkdir(mOSUserAppDir))
  151. {
  152. llwarns << "Could not create app user dir: " << mOSUserAppDir
  153. << " - Default to base dir: " << mOSUserDir << llendl;
  154. mOSUserAppDir = mOSUserDir;
  155. }
  156. if (!LLFile::mkdir(getFullPath(LL_PATH_LOGS)))
  157. {
  158. llwarns << "Could not create LL_PATH_LOGS dir "
  159. << getFullPath(LL_PATH_LOGS) << llendl;
  160. }
  161. if (!LLFile::mkdir(getFullPath(LL_PATH_USER_SETTINGS)))
  162. {
  163. llwarns << "Could not create LL_PATH_USER_SETTINGS dir "
  164. << getFullPath(LL_PATH_USER_SETTINGS) << llendl;
  165. }
  166. if (!LLFile::mkdir(getFullPath(LL_PATH_CACHE)))
  167. {
  168. llwarns << "Could not create LL_PATH_CACHE dir "
  169. << getFullPath(LL_PATH_CACHE) << llendl;
  170. }
  171. mCRTFile = getFullPath(LL_PATH_APP_SETTINGS, "ca-bundle.crt");
  172. dumpCurrentDirectories();
  173. }
  174. std::string LLDir::getCurPath()
  175. {
  176. char tmp_str[LL_MAX_PATH];
  177. if (getcwd(tmp_str, LL_MAX_PATH) == NULL)
  178. {
  179. llwarns << "Could not get current directory" << llendl;
  180. tmp_str[0] = '\0';
  181. }
  182. return tmp_str;
  183. }
  184. std::string LLDir::getLLPluginLauncher()
  185. {
  186. return mExecutableDir + "/llplugin/SLPlugin";
  187. }
  188. std::string LLDir::getLLPluginFilename(std::string base_name)
  189. {
  190. return mLLPluginDir + "/" + base_name + ".so";
  191. }