From 8e094e5a5bcbc7c4504784155b1458f974706beb Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 5 Mar 2012 18:09:34 -0500 Subject: [PATCH] Implement symlinkat() --- src/build/libroot/fs_darwin.cpp | 50 +++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/build/libroot/fs_darwin.cpp b/src/build/libroot/fs_darwin.cpp index d82b091039..7fde68221f 100644 --- a/src/build/libroot/fs_darwin.cpp +++ b/src/build/libroot/fs_darwin.cpp @@ -563,8 +563,54 @@ readlinkat(int fd, const char *path, char *buffer, size_t bufferSize) int symlinkat(const char *toPath, int fd, const char *symlinkPath) { - errno = ENOSYS; - return -1; + if (symlinkPath && symlinkPath[0] == '/') { + // symlinkPath is absolute, call symlink() ignoring fd + return symlink(toPath, symlinkPath); + } + + if (!fd) { + // fd is not a valid file descriptor + errno = EBADF; + return -1; + } + + if (fd == AT_FDCWD) { + // fd is set to AT_FDCWD, call symlink() + return symlink(toPath, symlinkPath); + } + + struct stat dirst; + if (fstat(fd, &dirst) < 0) { + // failed to grab stat information, fstat() sets errno + return -1; + } + + if ((dirst.st_mode & S_IFDIR) != 0) { + // fd does not point to a directory + errno = ENOTDIR; + return -1; + } + + char *dirpath; + dirpath = (char *)malloc(MAXPATHLEN); + if (dirpath == NULL) { + // ran out of memory allocating dirpath + errno = ENOMEM; + return -1; + } + + if (fcntl(fd, F_GETPATH, dirpath) < 0) { + // failed to get the path of fd, fcntl sets errno + return -1; + } + + if (strlcat(dirpath, symlinkPath, MAXPATHLEN) > MAXPATHLEN) { + // full path is too long, set errno and return + errno = ENAMETOOLONG; + return -1; + } + + return symlink(dirpath, symlinkPath); }