diff --git a/src/build/libroot/fs_darwin.cpp b/src/build/libroot/fs_darwin.cpp index 40d15807cd..9c972490cc 100644 --- a/src/build/libroot/fs_darwin.cpp +++ b/src/build/libroot/fs_darwin.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -18,8 +19,47 @@ int faccessat(int fd, const char* path, int accessMode, int flag) { - errno = ENOSYS; - return -1; + if ((flag & AT_EACCESS) == 0) { + // Perform access checks using the effective user and group IDs + // CURRENTLY UNSUPPORTED + errno = ENOTSUP; + return -1; + } + + if ((flag & AT_SYMLINK_NOFOLLOW) == 0) { + // do not dereference, instead return information about the link + // itself + // CURRENTLY UNSUPPORTED + errno = ENOTSUP; + return -1; + } + + if (fd == AT_FDCWD || (path && path[0] == '/')) { + // fd is set to AT_FDCWD or path is absolute, call access() + return access(path, accessMode); + } + + char *dirpath; + dirpath = (char *)malloc(MAXPATHLEN); + if (dirpath == NULL) { + errno = ENOMEM; + return -1; + } + + int status = fcntl(fd, F_GETPATH, dirpath); + if (status < 0) { + // failed to get the path of fd + errno = status; + return -1; + } + + if (strlcat(dirpath, path, MAXPATHLEN) > MAXPATHLEN) { + // full path is too long, set errno and return + errno = ENAMETOOLONG; + return -1; + } + + return access(dirpath, accessMode); }