aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/native/unix_jni_darwin.cc39
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) {