StandardPaths.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2023, Linus Groh <linusg@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/ByteString.h>
  8. #include <AK/LexicalPath.h>
  9. #include <AK/Platform.h>
  10. #include <AK/String.h>
  11. #include <AK/StringBuilder.h>
  12. #include <LibCore/SessionManagement.h>
  13. #include <LibCore/StandardPaths.h>
  14. #include <LibCore/System.h>
  15. #include <pwd.h>
  16. #include <stdlib.h>
  17. #include <unistd.h>
  18. #if defined(AK_OS_HAIKU)
  19. # include <FindDirectory.h>
  20. #endif
  21. namespace Core {
  22. ByteString StandardPaths::home_directory()
  23. {
  24. if (auto* home_env = getenv("HOME"))
  25. return LexicalPath::canonicalized_path(home_env);
  26. auto* pwd = getpwuid(getuid());
  27. ByteString path = pwd ? pwd->pw_dir : "/";
  28. endpwent();
  29. return LexicalPath::canonicalized_path(path);
  30. }
  31. ByteString StandardPaths::desktop_directory()
  32. {
  33. if (auto* desktop_directory = getenv("XDG_DESKTOP_DIR"))
  34. return LexicalPath::canonicalized_path(desktop_directory);
  35. StringBuilder builder;
  36. builder.append(home_directory());
  37. builder.append("/Desktop"sv);
  38. return LexicalPath::canonicalized_path(builder.to_byte_string());
  39. }
  40. ByteString StandardPaths::documents_directory()
  41. {
  42. if (auto* documents_directory = getenv("XDG_DOCUMENTS_DIR"))
  43. return LexicalPath::canonicalized_path(documents_directory);
  44. StringBuilder builder;
  45. builder.append(home_directory());
  46. builder.append("/Documents"sv);
  47. return LexicalPath::canonicalized_path(builder.to_byte_string());
  48. }
  49. ByteString StandardPaths::downloads_directory()
  50. {
  51. if (auto* downloads_directory = getenv("XDG_DOWNLOAD_DIR"))
  52. return LexicalPath::canonicalized_path(downloads_directory);
  53. StringBuilder builder;
  54. builder.append(home_directory());
  55. builder.append("/Downloads"sv);
  56. return LexicalPath::canonicalized_path(builder.to_byte_string());
  57. }
  58. ByteString StandardPaths::music_directory()
  59. {
  60. if (auto* music_directory = getenv("XDG_MUSIC_DIR"))
  61. return LexicalPath::canonicalized_path(music_directory);
  62. StringBuilder builder;
  63. builder.append(home_directory());
  64. builder.append("/Music"sv);
  65. return LexicalPath::canonicalized_path(builder.to_byte_string());
  66. }
  67. ByteString StandardPaths::pictures_directory()
  68. {
  69. if (auto* pictures_directory = getenv("XDG_PICTURES_DIR"))
  70. return LexicalPath::canonicalized_path(pictures_directory);
  71. StringBuilder builder;
  72. builder.append(home_directory());
  73. builder.append("/Pictures"sv);
  74. return LexicalPath::canonicalized_path(builder.to_byte_string());
  75. }
  76. ByteString StandardPaths::videos_directory()
  77. {
  78. if (auto* videos_directory = getenv("XDG_VIDEOS_DIR"))
  79. return LexicalPath::canonicalized_path(videos_directory);
  80. StringBuilder builder;
  81. builder.append(home_directory());
  82. #if defined(AK_OS_MACOS)
  83. builder.append("/Movies"sv);
  84. #else
  85. builder.append("/Videos"sv);
  86. #endif
  87. return LexicalPath::canonicalized_path(builder.to_byte_string());
  88. }
  89. ByteString StandardPaths::config_directory()
  90. {
  91. if (auto* config_directory = getenv("XDG_CONFIG_HOME"))
  92. return LexicalPath::canonicalized_path(config_directory);
  93. StringBuilder builder;
  94. builder.append(home_directory());
  95. #if defined(AK_OS_MACOS)
  96. builder.append("/Library/Preferences"sv);
  97. #elif defined(AK_OS_HAIKU)
  98. builder.append("/config/settings"sv);
  99. #else
  100. builder.append("/.config"sv);
  101. #endif
  102. return LexicalPath::canonicalized_path(builder.to_byte_string());
  103. }
  104. ByteString StandardPaths::data_directory()
  105. {
  106. if (auto* data_directory = getenv("XDG_DATA_HOME"))
  107. return LexicalPath::canonicalized_path(data_directory);
  108. StringBuilder builder;
  109. builder.append(home_directory());
  110. #if defined(AK_OS_SERENITY)
  111. builder.append("/.data"sv);
  112. #elif defined(AK_OS_MACOS)
  113. builder.append("/Library/Application Support"sv);
  114. #elif defined(AK_OS_HAIKU)
  115. builder.append("/config/non-packaged/data"sv);
  116. #else
  117. builder.append("/.local/share"sv);
  118. #endif
  119. return LexicalPath::canonicalized_path(builder.to_byte_string());
  120. }
  121. ErrorOr<ByteString> StandardPaths::runtime_directory()
  122. {
  123. if (auto* data_directory = getenv("XDG_RUNTIME_DIR"))
  124. return LexicalPath::canonicalized_path(data_directory);
  125. StringBuilder builder;
  126. #if defined(AK_OS_SERENITY)
  127. auto sid = TRY(Core::SessionManagement::root_session_id());
  128. builder.appendff("/tmp/session/{}", sid);
  129. #elif defined(AK_OS_MACOS)
  130. builder.append(home_directory());
  131. builder.append("/Library/Application Support"sv);
  132. #elif defined(AK_OS_HAIKU)
  133. builder.append("/boot/system/var/shared_memory"sv);
  134. #elif defined(AK_OS_LINUX)
  135. auto uid = getuid();
  136. builder.appendff("/run/user/{}", uid);
  137. #else
  138. // Just create a directory in /tmp that's owned by us with 0700
  139. auto uid = getuid();
  140. builder.appendff("/tmp/runtime_{}", uid);
  141. auto error_or_stat = System::stat(builder.string_view());
  142. if (error_or_stat.is_error()) {
  143. MUST(System::mkdir(builder.string_view(), 0700));
  144. } else {
  145. auto stat = error_or_stat.release_value();
  146. VERIFY(S_ISDIR(stat.st_mode));
  147. if ((stat.st_mode & 0777) != 0700)
  148. warnln("{} has unexpected mode flags {}", builder.string_view(), stat.st_mode);
  149. }
  150. #endif
  151. return LexicalPath::canonicalized_path(builder.to_byte_string());
  152. }
  153. ByteString StandardPaths::tempfile_directory()
  154. {
  155. return "/tmp";
  156. }
  157. ErrorOr<Vector<String>> StandardPaths::font_directories()
  158. {
  159. #if defined(AK_OS_HAIKU)
  160. Vector<String> paths_vector;
  161. char** paths;
  162. size_t paths_count;
  163. if (find_paths(B_FIND_PATH_FONTS_DIRECTORY, NULL, &paths, &paths_count) == B_OK) {
  164. for (size_t i = 0; i < paths_count; ++i) {
  165. StringBuilder builder;
  166. builder.append(paths[i], strlen(paths[i]));
  167. paths_vector.append(TRY(builder.to_string()));
  168. }
  169. }
  170. return paths_vector;
  171. #else
  172. return Vector { {
  173. # if defined(AK_OS_SERENITY)
  174. "/res/fonts"_string,
  175. # elif defined(AK_OS_MACOS)
  176. "/System/Library/Fonts"_string,
  177. "/Library/Fonts"_string,
  178. TRY(String::formatted("{}/Library/Fonts"sv, home_directory())),
  179. # else
  180. "/usr/share/fonts"_string,
  181. "/usr/local/share/fonts"_string,
  182. TRY(String::formatted("{}/.local/share/fonts"sv, home_directory())),
  183. # endif
  184. } };
  185. #endif
  186. }
  187. }