blob: 323a06519db7df54de6573a618d4f4ef770b08ae [file] [log] [blame]
David Sehr891a50e2017-10-27 17:01:07 -07001/*
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>
20#include <pthread.h>
21#include <sys/mman.h> // For madvise
22#include <sys/stat.h>
23#include <sys/syscall.h>
24#include <sys/types.h>
25#include <sys/wait.h>
26#include <unistd.h>
27
28// We need dladdr.
29#ifndef __APPLE__
30#ifndef _GNU_SOURCE
31#define _GNU_SOURCE
32#define DEFINED_GNU_SOURCE
33#endif
34#include <dlfcn.h>
35#include <libgen.h>
36#ifdef DEFINED_GNU_SOURCE
37#undef _GNU_SOURCE
38#undef DEFINED_GNU_SOURCE
39#endif
40#endif
41
42
43#include <memory>
44
45#include "android-base/stringprintf.h"
46#include "android-base/strings.h"
47
48#include "base/stl_util.h"
49#include "base/unix_file/fd_file.h"
50#include "dex_file-inl.h"
51#include "dex_file_loader.h"
52#include "dex_instruction.h"
53#include "oat_quick_method_header.h"
54#include "os.h"
55#include "scoped_thread_state_change-inl.h"
56#include "utf-inl.h"
57
58#if defined(__APPLE__)
59#include <crt_externs.h>
60#include <sys/syscall.h>
61#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
62#endif
63
64#if defined(__linux__)
65#include <linux/unistd.h>
66#endif
67
68namespace art {
69
70using android::base::StringAppendF;
71using android::base::StringPrintf;
72
73bool ReadFileToString(const std::string& file_name, std::string* result) {
74 File file(file_name, O_RDONLY, false);
75 if (!file.IsOpened()) {
76 return false;
77 }
78
79 std::vector<char> buf(8 * KB);
80 while (true) {
81 int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size()));
82 if (n == -1) {
83 return false;
84 }
85 if (n == 0) {
86 return true;
87 }
88 result->append(&buf[0], n);
89 }
90}
91
92bool PrintFileToLog(const std::string& file_name, LogSeverity level) {
93 File file(file_name, O_RDONLY, false);
94 if (!file.IsOpened()) {
95 return false;
96 }
97
98 constexpr size_t kBufSize = 256; // Small buffer. Avoid stack overflow and stack size warnings.
99 char buf[kBufSize + 1]; // +1 for terminator.
100 size_t filled_to = 0;
101 while (true) {
102 DCHECK_LT(filled_to, kBufSize);
103 int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to));
104 if (n <= 0) {
105 // Print the rest of the buffer, if it exists.
106 if (filled_to > 0) {
107 buf[filled_to] = 0;
108 LOG(level) << buf;
109 }
110 return n == 0;
111 }
112 // Scan for '\n'.
113 size_t i = filled_to;
114 bool found_newline = false;
115 for (; i < filled_to + n; ++i) {
116 if (buf[i] == '\n') {
117 // Found a line break, that's something to print now.
118 buf[i] = 0;
119 LOG(level) << buf;
120 // Copy the rest to the front.
121 if (i + 1 < filled_to + n) {
122 memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1);
123 filled_to = filled_to + n - i - 1;
124 } else {
125 filled_to = 0;
126 }
127 found_newline = true;
128 break;
129 }
130 }
131 if (found_newline) {
132 continue;
133 } else {
134 filled_to += n;
135 // Check if we must flush now.
136 if (filled_to == kBufSize) {
137 buf[kBufSize] = 0;
138 LOG(level) << buf;
139 filled_to = 0;
140 }
141 }
142 }
143}
144
145std::string GetAndroidRootSafe(std::string* error_msg) {
146 // Prefer ANDROID_ROOT if it's set.
147 const char* android_dir = getenv("ANDROID_ROOT");
148 if (android_dir != nullptr) {
149 if (!OS::DirectoryExists(android_dir)) {
150 *error_msg = StringPrintf("Failed to find ANDROID_ROOT directory %s", android_dir);
151 return "";
152 }
153 return android_dir;
154 }
155
156 // Check where libart is from, and derive from there. Only do this for non-Mac.
157#ifndef __APPLE__
158 {
159 Dl_info info;
160 if (dladdr(reinterpret_cast<const void*>(&GetAndroidRootSafe), /* out */ &info) != 0) {
161 // Make a duplicate of the fname so dirname can modify it.
162 UniqueCPtr<char> fname(strdup(info.dli_fname));
163
164 char* dir1 = dirname(fname.get()); // This is the lib directory.
165 char* dir2 = dirname(dir1); // This is the "system" directory.
166 if (OS::DirectoryExists(dir2)) {
167 std::string tmp = dir2; // Make a copy here so that fname can be released.
168 return tmp;
169 }
170 }
171 }
172#endif
173
174 // Try "/system".
175 if (!OS::DirectoryExists("/system")) {
176 *error_msg = "Failed to find ANDROID_ROOT directory /system";
177 return "";
178 }
179 return "/system";
180}
181
182std::string GetAndroidRoot() {
183 std::string error_msg;
184 std::string ret = GetAndroidRootSafe(&error_msg);
185 if (ret.empty()) {
186 LOG(FATAL) << error_msg;
187 UNREACHABLE();
188 }
189 return ret;
190}
191
192
193static const char* GetAndroidDirSafe(const char* env_var,
194 const char* default_dir,
195 std::string* error_msg) {
196 const char* android_dir = getenv(env_var);
197 if (android_dir == nullptr) {
198 if (OS::DirectoryExists(default_dir)) {
199 android_dir = default_dir;
200 } else {
201 *error_msg = StringPrintf("%s not set and %s does not exist", env_var, default_dir);
202 return nullptr;
203 }
204 }
205 if (!OS::DirectoryExists(android_dir)) {
206 *error_msg = StringPrintf("Failed to find %s directory %s", env_var, android_dir);
207 return nullptr;
208 }
209 return android_dir;
210}
211
212static const char* GetAndroidDir(const char* env_var, const char* default_dir) {
213 std::string error_msg;
214 const char* dir = GetAndroidDirSafe(env_var, default_dir, &error_msg);
215 if (dir != nullptr) {
216 return dir;
217 } else {
218 LOG(FATAL) << error_msg;
219 return nullptr;
220 }
221}
222
223const char* GetAndroidData() {
224 return GetAndroidDir("ANDROID_DATA", "/data");
225}
226
227const char* GetAndroidDataSafe(std::string* error_msg) {
228 return GetAndroidDirSafe("ANDROID_DATA", "/data", error_msg);
229}
230
231std::string GetDefaultBootImageLocation(std::string* error_msg) {
232 std::string android_root = GetAndroidRootSafe(error_msg);
233 if (android_root.empty()) {
234 return "";
235 }
236 return StringPrintf("%s/framework/boot.art", android_root.c_str());
237}
238
239void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache,
240 bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) {
241 CHECK(subdir != nullptr);
242 std::string error_msg;
243 const char* android_data = GetAndroidDataSafe(&error_msg);
244 if (android_data == nullptr) {
245 *have_android_data = false;
246 *dalvik_cache_exists = false;
247 *is_global_cache = false;
248 return;
249 } else {
250 *have_android_data = true;
251 }
252 const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
253 *dalvik_cache = dalvik_cache_root + subdir;
254 *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str());
255 *is_global_cache = strcmp(android_data, "/data") == 0;
256 if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) {
257 // Don't create the system's /data/dalvik-cache/... because it needs special permissions.
258 *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) &&
259 (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST));
260 }
261}
262
263std::string GetDalvikCache(const char* subdir) {
264 CHECK(subdir != nullptr);
265 const char* android_data = GetAndroidData();
266 const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
267 const std::string dalvik_cache = dalvik_cache_root + subdir;
268 if (!OS::DirectoryExists(dalvik_cache.c_str())) {
269 // TODO: Check callers. Traditional behavior is to not abort.
270 return "";
271 }
272 return dalvik_cache;
273}
274
275bool GetDalvikCacheFilename(const char* location, const char* cache_location,
276 std::string* filename, std::string* error_msg) {
277 if (location[0] != '/') {
278 *error_msg = StringPrintf("Expected path in location to be absolute: %s", location);
279 return false;
280 }
281 std::string cache_file(&location[1]); // skip leading slash
282 if (!android::base::EndsWith(location, ".dex") &&
283 !android::base::EndsWith(location, ".art") &&
284 !android::base::EndsWith(location, ".oat")) {
285 cache_file += "/";
286 cache_file += DexFileLoader::kClassesDex;
287 }
288 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
289 *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str());
290 return true;
291}
292
293std::string GetVdexFilename(const std::string& oat_location) {
294 return ReplaceFileExtension(oat_location, "vdex");
295}
296
297static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) {
298 // in = /foo/bar/baz
299 // out = /foo/bar/<isa>/baz
300 size_t pos = filename->rfind('/');
301 CHECK_NE(pos, std::string::npos) << *filename << " " << isa;
302 filename->insert(pos, "/", 1);
303 filename->insert(pos + 1, GetInstructionSetString(isa));
304}
305
306std::string GetSystemImageFilename(const char* location, const InstructionSet isa) {
307 // location = /system/framework/boot.art
308 // filename = /system/framework/<isa>/boot.art
309 std::string filename(location);
310 InsertIsaDirectory(isa, &filename);
311 return filename;
312}
313
314bool FileExists(const std::string& filename) {
315 struct stat buffer;
316 return stat(filename.c_str(), &buffer) == 0;
317}
318
319bool FileExistsAndNotEmpty(const std::string& filename) {
320 struct stat buffer;
321 if (stat(filename.c_str(), &buffer) != 0) {
322 return false;
323 }
324 return buffer.st_size > 0;
325}
326
327std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) {
328 const size_t last_ext = filename.find_last_of('.');
329 if (last_ext == std::string::npos) {
330 return filename + "." + new_extension;
331 } else {
332 return filename.substr(0, last_ext + 1) + new_extension;
333 }
334}
335
336int64_t GetFileSizeBytes(const std::string& filename) {
337 struct stat stat_buf;
338 int rc = stat(filename.c_str(), &stat_buf);
339 return rc == 0 ? stat_buf.st_size : -1;
340}
341
342int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice) {
343 DCHECK_LE(begin, end);
344 begin = AlignUp(begin, kPageSize);
345 end = AlignDown(end, kPageSize);
346 if (begin < end) {
347 int result = madvise(const_cast<uint8_t*>(begin), end - begin, advice);
348 if (result != 0) {
349 PLOG(WARNING) << "madvise failed " << result;
350 }
351 return result;
352 }
353 return 0;
354}
355
356} // namespace art