David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2011 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include "file_utils.h" |
| 18 | |
| 19 | #include <inttypes.h> |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 20 | #include <sys/stat.h> |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 21 | #include <sys/types.h> |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 22 | #ifndef _WIN32 |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 23 | #include <sys/wait.h> |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 24 | #endif |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 25 | #include <unistd.h> |
| 26 | |
| 27 | // We need dladdr. |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 28 | #if !defined(__APPLE__) && !defined(_WIN32) |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 29 | #ifndef _GNU_SOURCE |
| 30 | #define _GNU_SOURCE |
| 31 | #define DEFINED_GNU_SOURCE |
| 32 | #endif |
| 33 | #include <dlfcn.h> |
| 34 | #include <libgen.h> |
| 35 | #ifdef DEFINED_GNU_SOURCE |
| 36 | #undef _GNU_SOURCE |
| 37 | #undef DEFINED_GNU_SOURCE |
| 38 | #endif |
| 39 | #endif |
| 40 | |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 41 | #include <memory> |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 42 | #include <sstream> |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 43 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 44 | #include "android-base/file.h" |
Jiakai Zhang | 7fa7086 | 2021-09-15 08:56:56 +0000 | [diff] [blame] | 45 | #include "android-base/logging.h" |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 46 | #include "android-base/stringprintf.h" |
| 47 | #include "android-base/strings.h" |
David Sehr | b2ec9f5 | 2018-02-21 13:20:31 -0800 | [diff] [blame] | 48 | #include "base/bit_utils.h" |
David Sehr | 1979c64 | 2018-04-26 14:41:18 -0700 | [diff] [blame] | 49 | #include "base/globals.h" |
David Sehr | c431b9d | 2018-03-02 12:01:51 -0800 | [diff] [blame] | 50 | #include "base/os.h" |
David Sehr | 1979c64 | 2018-04-26 14:41:18 -0700 | [diff] [blame] | 51 | #include "base/stl_util.h" |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 52 | #include "base/unix_file/fd_file.h" |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 53 | |
| 54 | #if defined(__APPLE__) |
| 55 | #include <crt_externs.h> |
| 56 | #include <sys/syscall.h> |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 57 | |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 58 | #include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED |
| 59 | #endif |
| 60 | |
| 61 | #if defined(__linux__) |
| 62 | #include <linux/unistd.h> |
| 63 | #endif |
| 64 | |
| 65 | namespace art { |
| 66 | |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 67 | using android::base::StringPrintf; |
| 68 | |
David Sehr | c3e1895 | 2018-05-11 16:59:31 -0700 | [diff] [blame] | 69 | static constexpr const char* kClassesDex = "classes.dex"; |
Roland Levillain | 9ff900d | 2019-03-29 18:50:01 +0000 | [diff] [blame] | 70 | static constexpr const char* kAndroidRootEnvVar = "ANDROID_ROOT"; |
| 71 | static constexpr const char* kAndroidRootDefaultPath = "/system"; |
Chris Gross | 5477b8e | 2020-04-24 09:36:45 -0700 | [diff] [blame] | 72 | static constexpr const char* kAndroidSystemExtRootEnvVar = "ANDROID_SYSTEM_EXT"; |
| 73 | static constexpr const char* kAndroidSystemExtRootDefaultPath = "/system_ext"; |
Roland Levillain | 9ff900d | 2019-03-29 18:50:01 +0000 | [diff] [blame] | 74 | static constexpr const char* kAndroidDataEnvVar = "ANDROID_DATA"; |
| 75 | static constexpr const char* kAndroidDataDefaultPath = "/data"; |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 76 | static constexpr const char* kAndroidArtRootEnvVar = "ANDROID_ART_ROOT"; |
Roland Levillain | 9ff900d | 2019-03-29 18:50:01 +0000 | [diff] [blame] | 77 | static constexpr const char* kAndroidConscryptRootEnvVar = "ANDROID_CONSCRYPT_ROOT"; |
Victor Chang | d20e51d | 2020-05-05 16:01:19 +0100 | [diff] [blame] | 78 | static constexpr const char* kAndroidI18nRootEnvVar = "ANDROID_I18N_ROOT"; |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 79 | static constexpr const char* kApexDefaultPath = "/apex/"; |
| 80 | static constexpr const char* kArtApexDataEnvVar = "ART_APEX_DATA"; |
David Sehr | c3e1895 | 2018-05-11 16:59:31 -0700 | [diff] [blame] | 81 | |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 82 | // Get the "root" directory containing the "lib" directory where this instance |
| 83 | // of the libartbase library (which contains `GetRootContainingLibartbase`) is |
| 84 | // located: |
| 85 | // - on host this "root" is normally the Android Root (e.g. something like |
| 86 | // "$ANDROID_BUILD_TOP/out/host/linux-x86/"); |
Martin Stjernholm | ad909af | 2019-07-16 17:02:44 +0100 | [diff] [blame] | 87 | // - on target this "root" is normally the ART Root ("/apex/com.android.art"). |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 88 | // Return the empty string if that directory cannot be found or if this code is |
| 89 | // run on Windows or macOS. |
| 90 | static std::string GetRootContainingLibartbase() { |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 91 | #if !defined(_WIN32) && !defined(__APPLE__) |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 92 | // Check where libartbase is from, and derive from there. |
| 93 | Dl_info info; |
| 94 | if (dladdr(reinterpret_cast<const void*>(&GetRootContainingLibartbase), /* out */ &info) != 0) { |
| 95 | // Make a duplicate of the fname so dirname can modify it. |
| 96 | UniqueCPtr<char> fname(strdup(info.dli_fname)); |
| 97 | |
| 98 | char* dir1 = dirname(fname.get()); // This is the lib directory. |
| 99 | char* dir2 = dirname(dir1); // This is the "root" directory. |
| 100 | if (OS::DirectoryExists(dir2)) { |
| 101 | std::string tmp = dir2; // Make a copy here so that fname can be released. |
| 102 | return tmp; |
| 103 | } |
| 104 | } |
| 105 | #endif |
| 106 | return ""; |
| 107 | } |
| 108 | |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 109 | std::string GetAndroidRootSafe(std::string* error_msg) { |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 110 | #ifdef _WIN32 |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 111 | UNUSED(kAndroidRootEnvVar, kAndroidRootDefaultPath, GetRootContainingLibartbase); |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 112 | *error_msg = "GetAndroidRootSafe unsupported for Windows."; |
| 113 | return ""; |
| 114 | #else |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 115 | // Prefer ANDROID_ROOT if it's set. |
Roland Levillain | 9ff900d | 2019-03-29 18:50:01 +0000 | [diff] [blame] | 116 | const char* android_root_from_env = getenv(kAndroidRootEnvVar); |
| 117 | if (android_root_from_env != nullptr) { |
| 118 | if (!OS::DirectoryExists(android_root_from_env)) { |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 119 | *error_msg = |
| 120 | StringPrintf("Failed to find %s directory %s", kAndroidRootEnvVar, android_root_from_env); |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 121 | return ""; |
| 122 | } |
Roland Levillain | 9ff900d | 2019-03-29 18:50:01 +0000 | [diff] [blame] | 123 | return android_root_from_env; |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 124 | } |
| 125 | |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 126 | // On host, libartbase is currently installed in "$ANDROID_ROOT/lib" |
| 127 | // (e.g. something like "$ANDROID_BUILD_TOP/out/host/linux-x86/lib". Use this |
| 128 | // information to infer the location of the Android Root (on host only). |
| 129 | // |
| 130 | // Note that this could change in the future, if we decided to install ART |
Martin Stjernholm | ad909af | 2019-07-16 17:02:44 +0100 | [diff] [blame] | 131 | // artifacts in a different location, e.g. within an "ART APEX" directory. |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 132 | if (!kIsTargetBuild) { |
| 133 | std::string root_containing_libartbase = GetRootContainingLibartbase(); |
| 134 | if (!root_containing_libartbase.empty()) { |
| 135 | return root_containing_libartbase; |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 136 | } |
| 137 | } |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 138 | |
Roland Levillain | 9ff900d | 2019-03-29 18:50:01 +0000 | [diff] [blame] | 139 | // Try the default path. |
| 140 | if (!OS::DirectoryExists(kAndroidRootDefaultPath)) { |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 141 | *error_msg = |
| 142 | StringPrintf("Failed to find default Android Root directory %s", kAndroidRootDefaultPath); |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 143 | return ""; |
| 144 | } |
Roland Levillain | 9ff900d | 2019-03-29 18:50:01 +0000 | [diff] [blame] | 145 | return kAndroidRootDefaultPath; |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 146 | #endif |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 147 | } |
| 148 | |
| 149 | std::string GetAndroidRoot() { |
| 150 | std::string error_msg; |
| 151 | std::string ret = GetAndroidRootSafe(&error_msg); |
| 152 | if (ret.empty()) { |
| 153 | LOG(FATAL) << error_msg; |
| 154 | UNREACHABLE(); |
| 155 | } |
| 156 | return ret; |
| 157 | } |
| 158 | |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 159 | static const char* GetAndroidDirSafe(const char* env_var, |
| 160 | const char* default_dir, |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 161 | bool must_exist, |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 162 | std::string* error_msg) { |
| 163 | const char* android_dir = getenv(env_var); |
| 164 | if (android_dir == nullptr) { |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 165 | if (!must_exist || OS::DirectoryExists(default_dir)) { |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 166 | android_dir = default_dir; |
| 167 | } else { |
| 168 | *error_msg = StringPrintf("%s not set and %s does not exist", env_var, default_dir); |
| 169 | return nullptr; |
| 170 | } |
| 171 | } |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 172 | if (must_exist && !OS::DirectoryExists(android_dir)) { |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 173 | *error_msg = StringPrintf("Failed to find directory %s", android_dir); |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 174 | return nullptr; |
| 175 | } |
| 176 | return android_dir; |
| 177 | } |
| 178 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 179 | static const char* GetAndroidDir(const char* env_var, |
| 180 | const char* default_dir, |
| 181 | bool must_exist = true) { |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 182 | std::string error_msg; |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 183 | const char* dir = GetAndroidDirSafe(env_var, default_dir, must_exist, &error_msg); |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 184 | if (dir != nullptr) { |
| 185 | return dir; |
| 186 | } else { |
| 187 | LOG(FATAL) << error_msg; |
Elliott Hughes | c1896c9 | 2018-11-29 11:33:18 -0800 | [diff] [blame] | 188 | UNREACHABLE(); |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 189 | } |
| 190 | } |
| 191 | |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 192 | static std::string GetArtRootSafe(bool must_exist, /*out*/ std::string* error_msg) { |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 193 | #ifdef _WIN32 |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 194 | UNUSED(kAndroidArtRootEnvVar, kAndroidArtApexDefaultPath, GetRootContainingLibartbase); |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 195 | UNUSED(must_exist); |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 196 | *error_msg = "GetArtRootSafe unsupported for Windows."; |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 197 | return ""; |
| 198 | #else |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 199 | // Prefer ANDROID_ART_ROOT if it's set. |
| 200 | const char* android_art_root_from_env = getenv(kAndroidArtRootEnvVar); |
| 201 | if (android_art_root_from_env != nullptr) { |
| 202 | if (must_exist && !OS::DirectoryExists(android_art_root_from_env)) { |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 203 | *error_msg = StringPrintf( |
| 204 | "Failed to find %s directory %s", kAndroidArtRootEnvVar, android_art_root_from_env); |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 205 | return ""; |
| 206 | } |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 207 | return android_art_root_from_env; |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 208 | } |
| 209 | |
| 210 | // On target, libartbase is normally installed in |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 211 | // "$ANDROID_ART_ROOT/lib(64)" (e.g. something like |
Martin Stjernholm | ad909af | 2019-07-16 17:02:44 +0100 | [diff] [blame] | 212 | // "/apex/com.android.art/lib(64)". Use this information to infer the |
| 213 | // location of the ART Root (on target only). |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 214 | if (kIsTargetBuild) { |
| 215 | // *However*, a copy of libartbase may still be installed outside the |
Martin Stjernholm | ad909af | 2019-07-16 17:02:44 +0100 | [diff] [blame] | 216 | // ART Root on some occasions, as ART target gtests install their binaries |
| 217 | // and their dependencies under the Android Root, i.e. "/system" (see |
| 218 | // b/129534335). For that reason, we cannot reliably use |
| 219 | // `GetRootContainingLibartbase` to find the ART Root. (Note that this is |
| 220 | // not really a problem in practice, as Android Q devices define |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 221 | // ANDROID_ART_ROOT in their default environment, and will instead use |
Martin Stjernholm | ad909af | 2019-07-16 17:02:44 +0100 | [diff] [blame] | 222 | // the logic above anyway.) |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 223 | // |
| 224 | // TODO(b/129534335): Re-enable this logic when the only instance of |
Martin Stjernholm | ad909af | 2019-07-16 17:02:44 +0100 | [diff] [blame] | 225 | // libartbase on target is the one from the ART APEX. |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 226 | if ((false)) { |
| 227 | std::string root_containing_libartbase = GetRootContainingLibartbase(); |
| 228 | if (!root_containing_libartbase.empty()) { |
| 229 | return root_containing_libartbase; |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | // Try the default path. |
Martin Stjernholm | ad909af | 2019-07-16 17:02:44 +0100 | [diff] [blame] | 235 | if (must_exist && !OS::DirectoryExists(kAndroidArtApexDefaultPath)) { |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 236 | *error_msg = |
| 237 | StringPrintf("Failed to find default ART root directory %s", kAndroidArtApexDefaultPath); |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 238 | return ""; |
| 239 | } |
Martin Stjernholm | ad909af | 2019-07-16 17:02:44 +0100 | [diff] [blame] | 240 | return kAndroidArtApexDefaultPath; |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 241 | #endif |
| 242 | } |
| 243 | |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 244 | std::string GetArtRootSafe(std::string* error_msg) { |
| 245 | return GetArtRootSafe(/* must_exist= */ true, error_msg); |
Roland Levillain | 1ea8a62 | 2019-03-29 19:08:56 +0000 | [diff] [blame] | 246 | } |
| 247 | |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 248 | std::string GetArtRoot() { |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 249 | std::string error_msg; |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 250 | std::string ret = GetArtRootSafe(&error_msg); |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 251 | if (ret.empty()) { |
| 252 | LOG(FATAL) << error_msg; |
| 253 | UNREACHABLE(); |
| 254 | } |
| 255 | return ret; |
Roland Levillain | 1ea8a62 | 2019-03-29 19:08:56 +0000 | [diff] [blame] | 256 | } |
Roland Levillain | 2e3cb54 | 2019-04-05 18:00:04 +0100 | [diff] [blame] | 257 | |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 258 | std::string GetArtBinDir() { |
| 259 | // Environment variable `ANDROID_ART_ROOT` is defined as |
Martin Stjernholm | ad909af | 2019-07-16 17:02:44 +0100 | [diff] [blame] | 260 | // `$ANDROID_HOST_OUT/com.android.art` on host. However, host ART binaries are |
| 261 | // still installed in `$ANDROID_HOST_OUT/bin` (i.e. outside the ART Root). The |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 262 | // situation is cleaner on target, where `ANDROID_ART_ROOT` is |
Martin Stjernholm | ad909af | 2019-07-16 17:02:44 +0100 | [diff] [blame] | 263 | // `$ANDROID_ROOT/apex/com.android.art` and ART binaries are installed in |
| 264 | // `$ANDROID_ROOT/apex/com.android.art/bin`. |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 265 | std::string android_art_root = kIsTargetBuild ? GetArtRoot() : GetAndroidRoot(); |
| 266 | return android_art_root + "/bin"; |
Roland Levillain | fb6a5c0 | 2019-03-29 20:20:16 +0000 | [diff] [blame] | 267 | } |
| 268 | |
Roland Levillain | 2e3cb54 | 2019-04-05 18:00:04 +0100 | [diff] [blame] | 269 | std::string GetAndroidDataSafe(std::string* error_msg) { |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 270 | const char* android_dir = GetAndroidDirSafe(kAndroidDataEnvVar, |
| 271 | kAndroidDataDefaultPath, |
| 272 | /* must_exist= */ true, |
| 273 | error_msg); |
Roland Levillain | 2e3cb54 | 2019-04-05 18:00:04 +0100 | [diff] [blame] | 274 | return (android_dir != nullptr) ? android_dir : ""; |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 275 | } |
| 276 | |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 277 | std::string GetAndroidData() { return GetAndroidDir(kAndroidDataEnvVar, kAndroidDataDefaultPath); } |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 278 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 279 | std::string GetArtApexData() { |
| 280 | return GetAndroidDir(kArtApexDataEnvVar, kArtApexDataDefaultPath, /*must_exist=*/false); |
| 281 | } |
| 282 | |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 283 | static std::string GetPrebuiltPrimaryBootImageDir(const std::string& android_root) { |
| 284 | return StringPrintf("%s/framework", android_root.c_str()); |
| 285 | } |
| 286 | |
Jiakai Zhang | a329345 | 2022-01-12 20:04:11 +0000 | [diff] [blame] | 287 | std::string GetPrebuiltPrimaryBootImageDir() { |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 288 | std::string android_root = GetAndroidRoot(); |
| 289 | if (android_root.empty()) { |
| 290 | return ""; |
| 291 | } |
| 292 | return GetPrebuiltPrimaryBootImageDir(android_root); |
Jiakai Zhang | a329345 | 2022-01-12 20:04:11 +0000 | [diff] [blame] | 293 | } |
| 294 | |
Orion Hodson | 971068d | 2021-06-30 21:17:53 +0100 | [diff] [blame] | 295 | std::string GetDefaultBootImageLocation(const std::string& android_root, |
| 296 | bool deny_art_apex_data_files) { |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 297 | constexpr static const char* kEtcBootImageProf = "etc/boot-image.prof"; |
Jiakai Zhang | 8046b62 | 2022-01-28 21:40:17 +0000 | [diff] [blame] | 298 | constexpr static const char* kBootImageStem = "boot"; |
| 299 | constexpr static const char* kMinimalBootImageStem = "boot_minimal"; |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 300 | |
Jiakai Zhang | 884e22f | 2021-12-23 20:04:46 +0000 | [diff] [blame] | 301 | // If an update for the ART module has been been installed, a single boot image for the entire |
| 302 | // bootclasspath is in the ART APEX data directory. |
Orion Hodson | 971068d | 2021-06-30 21:17:53 +0100 | [diff] [blame] | 303 | if (kIsTargetBuild && !deny_art_apex_data_files) { |
Jiakai Zhang | 884e22f | 2021-12-23 20:04:46 +0000 | [diff] [blame] | 304 | const std::string boot_image = |
Jiakai Zhang | 8046b62 | 2022-01-28 21:40:17 +0000 | [diff] [blame] | 305 | GetApexDataDalvikCacheDirectory(InstructionSet::kNone) + "/" + kBootImageStem + ".art"; |
Jiakai Zhang | 884e22f | 2021-12-23 20:04:46 +0000 | [diff] [blame] | 306 | const std::string boot_image_filename = GetSystemImageFilename(boot_image.c_str(), kRuntimeISA); |
| 307 | if (OS::FileExists(boot_image_filename.c_str(), /*check_file_type=*/true)) { |
Jiakai Zhang | 8046b62 | 2022-01-28 21:40:17 +0000 | [diff] [blame] | 308 | // Typically "/data/misc/apexdata/com.android.art/dalvik-cache/boot.art!/apex/com.android.art |
| 309 | // /etc/boot-image.prof!/system/etc/boot-image.prof". |
Jiakai Zhang | 884e22f | 2021-12-23 20:04:46 +0000 | [diff] [blame] | 310 | return StringPrintf("%s!%s/%s!%s/%s", |
| 311 | boot_image.c_str(), |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 312 | kAndroidArtApexDefaultPath, |
Jiakai Zhang | 884e22f | 2021-12-23 20:04:46 +0000 | [diff] [blame] | 313 | kEtcBootImageProf, |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 314 | android_root.c_str(), |
| 315 | kEtcBootImageProf); |
| 316 | } else if (errno == EACCES) { |
| 317 | // Additional warning for potential SELinux misconfiguration. |
Jiakai Zhang | 884e22f | 2021-12-23 20:04:46 +0000 | [diff] [blame] | 318 | PLOG(ERROR) << "Default boot image check failed, could not stat: " << boot_image_filename; |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 319 | } |
Jiakai Zhang | 8046b62 | 2022-01-28 21:40:17 +0000 | [diff] [blame] | 320 | |
| 321 | // odrefresh can generate a minimal boot image, which only includes code from BCP jars in the |
| 322 | // ART module, when it fails to generate a single boot image for the entire bootclasspath (i.e., |
| 323 | // full boot image). Use it if it exists. |
| 324 | const std::string minimal_boot_image = GetApexDataDalvikCacheDirectory(InstructionSet::kNone) + |
| 325 | "/" + kMinimalBootImageStem + ".art"; |
| 326 | const std::string minimal_boot_image_filename = |
| 327 | GetSystemImageFilename(minimal_boot_image.c_str(), kRuntimeISA); |
| 328 | if (OS::FileExists(minimal_boot_image_filename.c_str(), /*check_file_type=*/true)) { |
| 329 | // Typically "/data/misc/apexdata/com.android.art/dalvik-cache/boot_minimal.art!/apex |
| 330 | // /com.android.art/etc/boot-image.prof:/nonx/boot_minimal-framework.art!/system/etc |
| 331 | // /boot-image.prof". |
| 332 | return StringPrintf("%s!%s/%s:/nonx/%s-framework.art!%s/%s", |
| 333 | minimal_boot_image.c_str(), |
| 334 | kAndroidArtApexDefaultPath, |
| 335 | kEtcBootImageProf, |
| 336 | kMinimalBootImageStem, |
| 337 | android_root.c_str(), |
| 338 | kEtcBootImageProf); |
| 339 | } else if (errno == EACCES) { |
| 340 | // Additional warning for potential SELinux misconfiguration. |
| 341 | PLOG(ERROR) << "Minimal boot image check failed, could not stat: " << boot_image_filename; |
| 342 | } |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 343 | } |
Jiakai Zhang | 884e22f | 2021-12-23 20:04:46 +0000 | [diff] [blame] | 344 | // Boot image consists of two parts: |
Jiakai Zhang | a329345 | 2022-01-12 20:04:11 +0000 | [diff] [blame] | 345 | // - the primary boot image (contains the Core Libraries) |
| 346 | // - the boot image extensions (contains framework libraries) |
Jiakai Zhang | 8046b62 | 2022-01-28 21:40:17 +0000 | [diff] [blame] | 347 | // Typically "/apex/com.android.art/javalib/boot.art!/apex/com.android.art/etc/boot-image.prof: |
| 348 | // /system/framework/boot-framework.art!/system/etc/boot-image.prof". |
| 349 | return StringPrintf("%s/%s.art!%s/%s:%s/framework/%s-framework.art!%s/%s", |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 350 | GetPrebuiltPrimaryBootImageDir(android_root).c_str(), |
Jiakai Zhang | 8046b62 | 2022-01-28 21:40:17 +0000 | [diff] [blame] | 351 | kBootImageStem, |
Ulyana Trafimovich | 81ba7db | 2019-12-18 17:33:07 +0000 | [diff] [blame] | 352 | kAndroidArtApexDefaultPath, |
Jiakai Zhang | a329345 | 2022-01-12 20:04:11 +0000 | [diff] [blame] | 353 | kEtcBootImageProf, |
Nicolas Geoffray | 2c2248c | 2020-03-06 14:50:45 +0000 | [diff] [blame] | 354 | android_root.c_str(), |
Jiakai Zhang | 8046b62 | 2022-01-28 21:40:17 +0000 | [diff] [blame] | 355 | kBootImageStem, |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 356 | android_root.c_str(), |
| 357 | kEtcBootImageProf); |
Nicolas Geoffray | de1b2a2 | 2019-02-27 09:10:57 +0000 | [diff] [blame] | 358 | } |
| 359 | |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 360 | std::string GetDefaultBootImageLocation(std::string* error_msg) { |
| 361 | std::string android_root = GetAndroidRootSafe(error_msg); |
| 362 | if (android_root.empty()) { |
| 363 | return ""; |
| 364 | } |
Orion Hodson | 971068d | 2021-06-30 21:17:53 +0100 | [diff] [blame] | 365 | return GetDefaultBootImageLocation(android_root, /*deny_art_apex_data_files=*/false); |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 366 | } |
| 367 | |
Alan Stokes | d4d21bf | 2021-10-13 11:07:25 +0100 | [diff] [blame] | 368 | static /*constinit*/ std::string_view dalvik_cache_sub_dir = "dalvik-cache"; |
| 369 | |
| 370 | void OverrideDalvikCacheSubDirectory(std::string sub_dir) { |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 371 | static std::string overridden_dalvik_cache_sub_dir; |
| 372 | overridden_dalvik_cache_sub_dir = std::move(sub_dir); |
| 373 | dalvik_cache_sub_dir = overridden_dalvik_cache_sub_dir; |
Alan Stokes | d4d21bf | 2021-10-13 11:07:25 +0100 | [diff] [blame] | 374 | } |
| 375 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 376 | static std::string GetDalvikCacheDirectory(std::string_view root_directory, |
| 377 | std::string_view sub_directory = {}) { |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 378 | std::stringstream oss; |
Alan Stokes | d4d21bf | 2021-10-13 11:07:25 +0100 | [diff] [blame] | 379 | oss << root_directory << '/' << dalvik_cache_sub_dir; |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 380 | if (!sub_directory.empty()) { |
| 381 | oss << '/' << sub_directory; |
| 382 | } |
| 383 | return oss.str(); |
| 384 | } |
| 385 | |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 386 | void GetDalvikCache(const char* subdir, |
| 387 | const bool create_if_absent, |
| 388 | std::string* dalvik_cache, |
| 389 | bool* have_android_data, |
| 390 | bool* dalvik_cache_exists, |
| 391 | bool* is_global_cache) { |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 392 | #ifdef _WIN32 |
| 393 | UNUSED(subdir); |
| 394 | UNUSED(create_if_absent); |
| 395 | UNUSED(dalvik_cache); |
| 396 | UNUSED(have_android_data); |
| 397 | UNUSED(dalvik_cache_exists); |
| 398 | UNUSED(is_global_cache); |
| 399 | LOG(FATAL) << "GetDalvikCache unsupported on Windows."; |
| 400 | #else |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 401 | CHECK(subdir != nullptr); |
Roland Levillain | 9ff900d | 2019-03-29 18:50:01 +0000 | [diff] [blame] | 402 | std::string unused_error_msg; |
Roland Levillain | 2e3cb54 | 2019-04-05 18:00:04 +0100 | [diff] [blame] | 403 | std::string android_data = GetAndroidDataSafe(&unused_error_msg); |
| 404 | if (android_data.empty()) { |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 405 | *have_android_data = false; |
| 406 | *dalvik_cache_exists = false; |
| 407 | *is_global_cache = false; |
| 408 | return; |
| 409 | } else { |
| 410 | *have_android_data = true; |
| 411 | } |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 412 | const std::string dalvik_cache_root = GetDalvikCacheDirectory(android_data); |
Roland Levillain | 2e3cb54 | 2019-04-05 18:00:04 +0100 | [diff] [blame] | 413 | *dalvik_cache = dalvik_cache_root + '/' + subdir; |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 414 | *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str()); |
Roland Levillain | 2e3cb54 | 2019-04-05 18:00:04 +0100 | [diff] [blame] | 415 | *is_global_cache = (android_data == kAndroidDataDefaultPath); |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 416 | if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) { |
| 417 | // Don't create the system's /data/dalvik-cache/... because it needs special permissions. |
| 418 | *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) && |
| 419 | (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST)); |
| 420 | } |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 421 | #endif |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 422 | } |
| 423 | |
Jiakai Zhang | 7fa7086 | 2021-09-15 08:56:56 +0000 | [diff] [blame] | 424 | // Returns a path formed by encoding the dex location into the filename. The path returned will be |
| 425 | // rooted at `cache_location`. |
| 426 | static bool GetLocationEncodedFilename(const char* location, |
| 427 | const char* cache_location, |
| 428 | std::string* filename, |
| 429 | std::string* error_msg) { |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 430 | if (location[0] != '/') { |
| 431 | *error_msg = StringPrintf("Expected path in location to be absolute: %s", location); |
| 432 | return false; |
| 433 | } |
| 434 | std::string cache_file(&location[1]); // skip leading slash |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 435 | if (!android::base::EndsWith(location, ".dex") && !android::base::EndsWith(location, ".art") && |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 436 | !android::base::EndsWith(location, ".oat")) { |
| 437 | cache_file += "/"; |
David Sehr | c3e1895 | 2018-05-11 16:59:31 -0700 | [diff] [blame] | 438 | cache_file += kClassesDex; |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 439 | } |
| 440 | std::replace(cache_file.begin(), cache_file.end(), '/', '@'); |
| 441 | *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str()); |
| 442 | return true; |
| 443 | } |
| 444 | |
Jiakai Zhang | 7fa7086 | 2021-09-15 08:56:56 +0000 | [diff] [blame] | 445 | bool GetDalvikCacheFilename(const char* location, |
| 446 | const char* cache_location, |
| 447 | std::string* filename, |
| 448 | std::string* error_msg) { |
| 449 | return GetLocationEncodedFilename(location, cache_location, filename, error_msg); |
| 450 | } |
| 451 | |
Victor Hsieh | fb00761 | 2021-12-01 16:51:20 -0800 | [diff] [blame] | 452 | std::string GetApexDataDalvikCacheDirectory(InstructionSet isa) { |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 453 | if (isa != InstructionSet::kNone) { |
| 454 | return GetDalvikCacheDirectory(GetArtApexData(), GetInstructionSetString(isa)); |
| 455 | } |
| 456 | return GetDalvikCacheDirectory(GetArtApexData()); |
| 457 | } |
| 458 | |
| 459 | static std::string GetApexDataDalvikCacheFilename(std::string_view dex_location, |
| 460 | InstructionSet isa, |
Jiakai Zhang | d61b021 | 2021-07-08 10:20:26 +0800 | [diff] [blame] | 461 | bool is_boot_classpath_location, |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 462 | std::string_view file_extension) { |
Jiakai Zhang | d61b021 | 2021-07-08 10:20:26 +0800 | [diff] [blame] | 463 | if (LocationIsOnApex(dex_location) && is_boot_classpath_location) { |
| 464 | // We don't compile boot images for updatable APEXes. |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 465 | return {}; |
| 466 | } |
| 467 | std::string apex_data_dalvik_cache = GetApexDataDalvikCacheDirectory(isa); |
Jiakai Zhang | d61b021 | 2021-07-08 10:20:26 +0800 | [diff] [blame] | 468 | if (!is_boot_classpath_location) { |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 469 | // Arguments: "/system/framework/xyz.jar", "arm", true, "odex" |
| 470 | // Result: |
| 471 | // "/data/misc/apexdata/com.android.art/dalvik-cache/arm/system@framework@xyz.jar@classes.odex" |
| 472 | std::string result, unused_error_msg; |
| 473 | GetDalvikCacheFilename(std::string{dex_location}.c_str(), |
| 474 | apex_data_dalvik_cache.c_str(), |
| 475 | &result, |
| 476 | &unused_error_msg); |
| 477 | return ReplaceFileExtension(result, file_extension); |
| 478 | } else { |
| 479 | // Arguments: "/system/framework/xyz.jar", "x86_64", false, "art" |
| 480 | // Results: "/data/misc/apexdata/com.android.art/dalvik-cache/x86_64/boot-xyz.jar@classes.art" |
| 481 | std::string basename = android::base::Basename(std::string{dex_location}); |
| 482 | return apex_data_dalvik_cache + "/boot-" + ReplaceFileExtension(basename, file_extension); |
| 483 | } |
| 484 | } |
| 485 | |
| 486 | std::string GetApexDataOatFilename(std::string_view location, InstructionSet isa) { |
Jiakai Zhang | d61b021 | 2021-07-08 10:20:26 +0800 | [diff] [blame] | 487 | return GetApexDataDalvikCacheFilename(location, isa, /*is_boot_classpath_location=*/true, "oat"); |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 488 | } |
| 489 | |
| 490 | std::string GetApexDataOdexFilename(std::string_view location, InstructionSet isa) { |
Jiakai Zhang | d61b021 | 2021-07-08 10:20:26 +0800 | [diff] [blame] | 491 | return GetApexDataDalvikCacheFilename( |
| 492 | location, isa, /*is_boot_classpath_location=*/false, "odex"); |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 493 | } |
| 494 | |
| 495 | std::string GetApexDataBootImage(std::string_view dex_location) { |
| 496 | return GetApexDataDalvikCacheFilename(dex_location, |
| 497 | InstructionSet::kNone, |
Jiakai Zhang | d61b021 | 2021-07-08 10:20:26 +0800 | [diff] [blame] | 498 | /*is_boot_classpath_location=*/true, |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 499 | kArtImageExtension); |
| 500 | } |
| 501 | |
| 502 | std::string GetApexDataImage(std::string_view dex_location) { |
| 503 | return GetApexDataDalvikCacheFilename(dex_location, |
| 504 | InstructionSet::kNone, |
Jiakai Zhang | d61b021 | 2021-07-08 10:20:26 +0800 | [diff] [blame] | 505 | /*is_boot_classpath_location=*/false, |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 506 | kArtImageExtension); |
| 507 | } |
| 508 | |
| 509 | std::string GetApexDataDalvikCacheFilename(std::string_view dex_location, |
| 510 | InstructionSet isa, |
| 511 | std::string_view file_extension) { |
| 512 | return GetApexDataDalvikCacheFilename( |
Jiakai Zhang | d61b021 | 2021-07-08 10:20:26 +0800 | [diff] [blame] | 513 | dex_location, isa, /*is_boot_classpath_location=*/false, file_extension); |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 514 | } |
| 515 | |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 516 | std::string GetVdexFilename(const std::string& oat_location) { |
| 517 | return ReplaceFileExtension(oat_location, "vdex"); |
| 518 | } |
| 519 | |
Nicolas Geoffray | 327cfcf | 2021-10-12 14:13:25 +0100 | [diff] [blame] | 520 | std::string GetDmFilename(const std::string& dex_location) { |
| 521 | return ReplaceFileExtension(dex_location, "dm"); |
| 522 | } |
| 523 | |
Jiakai Zhang | 7fa7086 | 2021-09-15 08:56:56 +0000 | [diff] [blame] | 524 | std::string GetSystemOdexFilenameForApex(std::string_view location, InstructionSet isa) { |
| 525 | DCHECK(LocationIsOnApex(location)); |
| 526 | std::string dir = GetAndroidRoot() + "/framework/oat/" + GetInstructionSetString(isa); |
| 527 | std::string result, error_msg; |
| 528 | bool ret = |
| 529 | GetLocationEncodedFilename(std::string{location}.c_str(), dir.c_str(), &result, &error_msg); |
| 530 | // This should never fail. The function fails only if the location is not absolute, and a location |
| 531 | // on /apex is always absolute. |
| 532 | DCHECK(ret) << error_msg; |
| 533 | return ReplaceFileExtension(result, "odex"); |
| 534 | } |
| 535 | |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 536 | static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) { |
| 537 | // in = /foo/bar/baz |
| 538 | // out = /foo/bar/<isa>/baz |
| 539 | size_t pos = filename->rfind('/'); |
| 540 | CHECK_NE(pos, std::string::npos) << *filename << " " << isa; |
| 541 | filename->insert(pos, "/", 1); |
| 542 | filename->insert(pos + 1, GetInstructionSetString(isa)); |
| 543 | } |
| 544 | |
| 545 | std::string GetSystemImageFilename(const char* location, const InstructionSet isa) { |
| 546 | // location = /system/framework/boot.art |
| 547 | // filename = /system/framework/<isa>/boot.art |
| 548 | std::string filename(location); |
| 549 | InsertIsaDirectory(isa, &filename); |
| 550 | return filename; |
| 551 | } |
| 552 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 553 | std::string ReplaceFileExtension(std::string_view filename, std::string_view new_extension) { |
Vladimir Marko | 62c2d71 | 2018-03-09 12:54:05 +0000 | [diff] [blame] | 554 | const size_t last_ext = filename.find_last_of("./"); |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 555 | std::string result; |
Vladimir Marko | 62c2d71 | 2018-03-09 12:54:05 +0000 | [diff] [blame] | 556 | if (last_ext == std::string::npos || filename[last_ext] != '.') { |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 557 | result.reserve(filename.size() + 1 + new_extension.size()); |
| 558 | result.append(filename).append(".").append(new_extension); |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 559 | } else { |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 560 | result.reserve(last_ext + 1 + new_extension.size()); |
| 561 | result.append(filename.substr(0, last_ext + 1)).append(new_extension); |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 562 | } |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 563 | return result; |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 564 | } |
| 565 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 566 | bool LocationIsOnArtApexData(std::string_view location) { |
| 567 | const std::string art_apex_data = GetArtApexData(); |
| 568 | return android::base::StartsWith(location, art_apex_data); |
| 569 | } |
| 570 | |
| 571 | bool LocationIsOnArtModule(std::string_view full_path) { |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 572 | std::string unused_error_msg; |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 573 | std::string module_path = GetArtRootSafe(/* must_exist= */ kIsTargetBuild, &unused_error_msg); |
Roland Levillain | 50eec3d | 2019-04-05 18:53:58 +0100 | [diff] [blame] | 574 | if (module_path.empty()) { |
| 575 | return false; |
| 576 | } |
| 577 | return android::base::StartsWith(full_path, module_path); |
| 578 | } |
| 579 | |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 580 | static bool StartsWithSlash(const char* str) { |
| 581 | DCHECK(str != nullptr); |
| 582 | return str[0] == '/'; |
| 583 | } |
| 584 | |
| 585 | static bool EndsWithSlash(const char* str) { |
| 586 | DCHECK(str != nullptr); |
| 587 | size_t len = strlen(str); |
| 588 | return len > 0 && str[len - 1] == '/'; |
| 589 | } |
| 590 | |
| 591 | // Returns true if `full_path` is located in folder either provided with `env_var` |
| 592 | // or in `default_path` otherwise. The caller may optionally provide a `subdir` |
| 593 | // which will be appended to the tested prefix. |
Nicolas Geoffray | 59c2103 | 2021-03-02 13:05:03 +0000 | [diff] [blame] | 594 | // `default_path` and the value of environment variable `env_var` |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 595 | // are expected to begin with a slash and not end with one. If this ever changes, |
| 596 | // the path-building logic should be updated. |
Nicolas Geoffray | 59c2103 | 2021-03-02 13:05:03 +0000 | [diff] [blame] | 597 | static bool IsLocationOn(std::string_view full_path, |
| 598 | const char* env_var, |
| 599 | const char* default_path, |
| 600 | const char* subdir = nullptr) { |
Roland Levillain | 9ff900d | 2019-03-29 18:50:01 +0000 | [diff] [blame] | 601 | std::string unused_error_msg; |
Nicolas Geoffray | 59c2103 | 2021-03-02 13:05:03 +0000 | [diff] [blame] | 602 | const char* path = GetAndroidDirSafe(env_var, |
| 603 | default_path, |
| 604 | /* must_exist= */ kIsTargetBuild, |
| 605 | &unused_error_msg); |
| 606 | if (path == nullptr) { |
Orion Hodson | 12162de | 2019-01-21 16:01:30 +0000 | [diff] [blame] | 607 | return false; |
| 608 | } |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 609 | |
| 610 | // Build the path which we will check is a prefix of `full_path`. The prefix must |
David Brazdil | 240cb2a | 2019-04-26 13:25:45 +0100 | [diff] [blame] | 611 | // end with a slash, so that "/foo/bar" does not match "/foo/barz". |
Nicolas Geoffray | 59c2103 | 2021-03-02 13:05:03 +0000 | [diff] [blame] | 612 | DCHECK(StartsWithSlash(path)) << path; |
| 613 | std::string path_prefix(path); |
David Brazdil | 240cb2a | 2019-04-26 13:25:45 +0100 | [diff] [blame] | 614 | if (!EndsWithSlash(path_prefix.c_str())) { |
| 615 | path_prefix.append("/"); |
| 616 | } |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 617 | if (subdir != nullptr) { |
David Brazdil | 240cb2a | 2019-04-26 13:25:45 +0100 | [diff] [blame] | 618 | // If `subdir` is provided, we assume it is provided without a starting slash |
| 619 | // but ending with one, e.g. "sub/dir/". `path_prefix` ends with a slash at |
| 620 | // this point, so we simply append `subdir`. |
| 621 | DCHECK(!StartsWithSlash(subdir) && EndsWithSlash(subdir)) << subdir; |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 622 | path_prefix.append(subdir); |
| 623 | } |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 624 | |
| 625 | return android::base::StartsWith(full_path, path_prefix); |
| 626 | } |
| 627 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 628 | bool LocationIsOnSystemFramework(std::string_view full_path) { |
Nicolas Geoffray | 59c2103 | 2021-03-02 13:05:03 +0000 | [diff] [blame] | 629 | return IsLocationOn(full_path, |
| 630 | kAndroidRootEnvVar, |
| 631 | kAndroidRootDefaultPath, |
| 632 | /* subdir= */ "framework/"); |
David Brazdil | 3c83921 | 2019-03-04 14:29:50 +0000 | [diff] [blame] | 633 | } |
| 634 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 635 | bool LocationIsOnSystemExtFramework(std::string_view full_path) { |
Nicolas Geoffray | 59c2103 | 2021-03-02 13:05:03 +0000 | [diff] [blame] | 636 | return IsLocationOn(full_path, |
| 637 | kAndroidSystemExtRootEnvVar, |
| 638 | kAndroidSystemExtRootDefaultPath, |
| 639 | /* subdir= */ "framework/") || |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 640 | // When the 'system_ext' partition is not present, builds will create |
| 641 | // '/system/system_ext' instead. |
| 642 | IsLocationOn(full_path, |
| 643 | kAndroidRootEnvVar, |
| 644 | kAndroidRootDefaultPath, |
| 645 | /* subdir= */ "system_ext/framework/"); |
Chris Gross | 5477b8e | 2020-04-24 09:36:45 -0700 | [diff] [blame] | 646 | } |
| 647 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 648 | bool LocationIsOnConscryptModule(std::string_view full_path) { |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 649 | return IsLocationOn(full_path, kAndroidConscryptRootEnvVar, kAndroidConscryptApexDefaultPath); |
Orion Hodson | 12162de | 2019-01-21 16:01:30 +0000 | [diff] [blame] | 650 | } |
| 651 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 652 | bool LocationIsOnI18nModule(std::string_view full_path) { |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 653 | return IsLocationOn(full_path, kAndroidI18nRootEnvVar, kAndroidI18nApexDefaultPath); |
Victor Chang | d20e51d | 2020-05-05 16:01:19 +0100 | [diff] [blame] | 654 | } |
| 655 | |
Orion Hodson | d6e00a7 | 2021-02-10 13:52:40 +0000 | [diff] [blame] | 656 | bool LocationIsOnApex(std::string_view full_path) { |
David Brazdil | e7e26d1 | 2019-02-28 15:04:14 +0000 | [diff] [blame] | 657 | return android::base::StartsWith(full_path, kApexDefaultPath); |
| 658 | } |
| 659 | |
Alan Stokes | a2e3936 | 2022-01-06 14:09:00 +0000 | [diff] [blame] | 660 | std::string_view ApexNameFromLocation(std::string_view full_path) { |
| 661 | if (!android::base::StartsWith(full_path, kApexDefaultPath)) { |
| 662 | return {}; |
| 663 | } |
| 664 | size_t start = strlen(kApexDefaultPath); |
| 665 | size_t end = full_path.find('/', start); |
| 666 | if (end == std::string_view::npos) { |
| 667 | return {}; |
| 668 | } |
| 669 | return full_path.substr(start, end - start); |
| 670 | } |
| 671 | |
Orion Hodson | 094b1cf | 2021-06-08 09:28:28 +0100 | [diff] [blame] | 672 | bool LocationIsOnSystem(const std::string& location) { |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 673 | #ifdef _WIN32 |
Orion Hodson | 094b1cf | 2021-06-08 09:28:28 +0100 | [diff] [blame] | 674 | UNUSED(location); |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 675 | LOG(FATAL) << "LocationIsOnSystem is unsupported on Windows."; |
| 676 | return false; |
| 677 | #else |
Nicolas Geoffray | ea55f3d | 2021-09-07 12:16:56 +0100 | [diff] [blame] | 678 | return android::base::StartsWith(location, GetAndroidRoot().c_str()); |
David Sehr | 10db8fe | 2018-07-18 11:01:20 -0700 | [diff] [blame] | 679 | #endif |
Nicolas Geoffray | 2974260 | 2017-12-14 10:09:03 +0000 | [diff] [blame] | 680 | } |
| 681 | |
Orion Hodson | 971068d | 2021-06-30 21:17:53 +0100 | [diff] [blame] | 682 | bool LocationIsTrusted(const std::string& location, bool trust_art_apex_data_files) { |
Nicolas Geoffray | ea55f3d | 2021-09-07 12:16:56 +0100 | [diff] [blame] | 683 | if (LocationIsOnSystem(location) || LocationIsOnArtModule(location)) { |
Orion Hodson | 971068d | 2021-06-30 21:17:53 +0100 | [diff] [blame] | 684 | return true; |
| 685 | } |
| 686 | return LocationIsOnArtApexData(location) & trust_art_apex_data_files; |
Orion Hodson | 094b1cf | 2021-06-08 09:28:28 +0100 | [diff] [blame] | 687 | } |
| 688 | |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 689 | bool ArtModuleRootDistinctFromAndroidRoot() { |
David Brazdil | 2df4bfb | 2019-04-10 00:30:35 +0100 | [diff] [blame] | 690 | std::string error_msg; |
| 691 | const char* android_root = GetAndroidDirSafe(kAndroidRootEnvVar, |
| 692 | kAndroidRootDefaultPath, |
| 693 | /* must_exist= */ kIsTargetBuild, |
| 694 | &error_msg); |
Martin Stjernholm | e58624f | 2019-09-20 15:53:40 +0100 | [diff] [blame] | 695 | const char* art_root = GetAndroidDirSafe(kAndroidArtRootEnvVar, |
| 696 | kAndroidArtApexDefaultPath, |
| 697 | /* must_exist= */ kIsTargetBuild, |
| 698 | &error_msg); |
Jiakai Zhang | 0bdef31 | 2022-02-16 17:45:39 +0000 | [diff] [blame] | 699 | return (android_root != nullptr) && (art_root != nullptr) && |
| 700 | (std::string_view(android_root) != std::string_view(art_root)); |
David Brazdil | bfaba28 | 2019-03-15 11:35:51 +0000 | [diff] [blame] | 701 | } |
| 702 | |
Josh Gao | 35696a0 | 2018-08-30 17:24:16 -0700 | [diff] [blame] | 703 | int DupCloexec(int fd) { |
| 704 | #if defined(__linux__) |
| 705 | return fcntl(fd, F_DUPFD_CLOEXEC, 0); |
| 706 | #else |
| 707 | return dup(fd); |
| 708 | #endif |
| 709 | } |
| 710 | |
David Sehr | 891a50e | 2017-10-27 17:01:07 -0700 | [diff] [blame] | 711 | } // namespace art |