diff --git a/starboard/android/shared/posix_emu/stat.cc b/starboard/android/shared/posix_emu/stat.cc index b2b81a48b1c6..41600c0be508 100644 --- a/starboard/android/shared/posix_emu/stat.cc +++ b/starboard/android/shared/posix_emu/stat.cc @@ -15,7 +15,9 @@ #include #include #include +#include #include +#include #include "starboard/android/shared/file_internal.h" @@ -38,7 +40,21 @@ int __wrap_stat(const char* path, struct stat* info) { int __wrap_fstatat(int dirfd, const char* path, struct stat* info, int flags) { if (!IsAndroidAssetPath(path)) { - return __real_fstatat(dirfd, path, info, flags); + int retval = __real_fstatat(dirfd, path, info, flags); + if (retval == 0 && (flags & AT_SYMLINK_NOFOLLOW) && S_ISLNK(info->st_mode)) { + // POSIX requires a symlink's st_size to be the length of the target path. + // Android's /data filesystem reports a different value, so normalize it + // via readlink. Save and restore errno so a readlinkat failure doesn't + // pollute it while the call still reports success. + int saved_errno = errno; + char buf[PATH_MAX]; + ssize_t len = readlinkat(dirfd, path, buf, sizeof(buf)); + if (len >= 0) { + info->st_size = len; + } + errno = saved_errno; + } + return retval; } if (info == NULL) {