diff options
-rw-r--r-- | src/main/native/unix_jni_darwin.cc | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/src/main/native/unix_jni_darwin.cc b/src/main/native/unix_jni_darwin.cc index 3d7063d3be..017df43d31 100644 --- a/src/main/native/unix_jni_darwin.cc +++ b/src/main/native/unix_jni_darwin.cc @@ -16,11 +16,16 @@ #include <assert.h> #include <errno.h> +#include <fcntl.h> +#include <stdlib.h> #include <string.h> #include <sys/stat.h> +#include <sys/syslimits.h> #include <string> +const int PATH_MAX2 = PATH_MAX * 2; + using std::string; // See unix_jni.h. @@ -33,9 +38,39 @@ string ErrorMessage(int error_number) { return string(buf); } + int portable_fstatat(int dirfd, char *name, struct stat *statbuf, int flags) { - errno = ENOSYS; - return -1; + char dirPath[PATH_MAX2]; // Have enough room for relative path + + // No fstatat under darwin, simulate it + if (flags != 0) { + // We don't support any flags + errno = ENOSYS; + return -1; + } + if (strlen(name) == 0 || name[0] == '/') { + // Absolute path, simply stat + return stat(name, statbuf); + } + // Relative path, construct an absolute path + if (fcntl(dirfd, F_GETPATH, dirPath) == -1) { + return -1; + } + int l = strlen(dirPath); + if (dirPath[l-1] != '/') { + // dirPath is twice the PATH_MAX size, we always have room for the extra / + dirPath[l] = '/'; + dirPath[l+1] = 0; + l++; + } + strncat(dirPath, name, PATH_MAX2-l-1); + char *newpath = realpath(dirPath, NULL); // this resolve the relative path + if (newpath == NULL) { + return -1; + } + int r = stat(newpath, statbuf); + free(newpath); + return r; } int StatSeconds(const struct stat &statbuf, StatTimes t) { |