Index: runtime/bin/file_linux.cc |
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc |
index 9fc4bd15dcb442d07d826dbd1f789671397c23e5..0a437f14874fac8435f87fbc11404439ff5390cf 100644 |
--- a/runtime/bin/file_linux.cc |
+++ b/runtime/bin/file_linux.cc |
@@ -368,14 +368,21 @@ char* File::LinkTarget(const char* pathname) { |
errno = ENOENT; |
return NULL; |
} |
- size_t target_size = link_stats.st_size; |
+ // Don't rely on the link_stats.st_size for the size of the link |
+ // target. For some filesystems, e.g. procfs, this value is always |
+ // 0. Also the link might have changed before the readlink call. |
+ const int kBufferSize = PATH_MAX + 1; |
+ char target[kBufferSize]; |
+ size_t target_size = TEMP_FAILURE_RETRY( |
+ readlink(pathname, target, kBufferSize)); |
+ if (target_size <= 0) { |
+ return NULL; |
+ } |
char* target_name = reinterpret_cast<char*>(malloc(target_size + 1)); |
- size_t read_size = NO_RETRY_EXPECTED( |
- readlink(pathname, target_name, target_size + 1)); |
- if (read_size != target_size) { |
- free(target_name); |
+ if (target_name == NULL) { |
return NULL; |
} |
+ memmove(target_name, target, target_size); |
target_name[target_size] = '\0'; |
return target_name; |
} |