[haiku-commits] haiku: hrev43834 - src/build/libroot headers/build/host/darwin/sys

  • From: jscipione@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 9 Mar 2012 05:41:37 +0100 (CET)

hrev43834 adds 1 changeset to branch 'master'
old head: 89a2b4812c2efb6d269be70a970054a53095b4dd
new head: 81b45e484a2f71f1235d48ab743c20357f070593

----------------------------------------------------------------------------

81b45e4: Fix build on Mac OS X 10.6 gcc2 and gcc4 and 10.7 gcc4 by adding some 
Mac OS X specific files that implement missing *at() functions.
  Mac OS X 10.7 generates a gcc2 cross-compiler that fails when assigning NULL 
to a static method pointer so is still broken.
  Added a weak attribute in driver_settings.cpp.
  Move futimesat() from fs.cpp to fs_darwin.cpp since it is implimented on 
FreeBSD.
  Implemented eaccess(), for the AT_EACCESS flag of faccessat()
  Fix configure script to correctly detect case-sensitive file system

                                     [ John Scipione <jscipione@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev43834
Commit:      81b45e484a2f71f1235d48ab743c20357f070593
URL:         http://cgit.haiku-os.org/haiku/commit/?id=81b45e4
Author:      John Scipione <jscipione@xxxxxxxxx>
Date:        Thu Mar  1 00:42:59 2012 UTC

----------------------------------------------------------------------------

8 files changed, 869 insertions(+), 126 deletions(-)
configure                                 |    2 +-
headers/build/host/darwin/sys/stat.h      |   31 ++
src/build/libroot/Jamfile                 |    4 +
src/build/libroot/fs.cpp                  |  132 +++++
src/build/libroot/fs_darwin.cpp           |  659 +++++++++++++++++++++++++
src/build/libroot/fs_darwin.h             |   41 ++
src/build/libroot/fs_freebsd.cpp          |  124 -----
src/system/libroot/os/driver_settings.cpp |    2 +-

----------------------------------------------------------------------------

diff --git a/configure b/configure
index 1edda47..9d6ca5a 100755
--- a/configure
+++ b/configure
@@ -473,7 +473,7 @@ done
 
 # check for case-sensitive filesystem if on darwin
 if [ $HOST_PLATFORM = "darwin" ]; then
-       diskutil info $(pwd) | grep -i "case-sensitive" > /dev/null
+       diskutil info $(pwd)/.. | grep -i "case-sensitive" > /dev/null
        if [ $? != 0 ]; then
                echo "You need a case-sensitive file-system to build Haiku."
                echo "Please see the following guide on how to set one up:"
diff --git a/headers/build/host/darwin/sys/stat.h 
b/headers/build/host/darwin/sys/stat.h
new file mode 100644
index 0000000..1a43b14
--- /dev/null
+++ b/headers/build/host/darwin/sys/stat.h
@@ -0,0 +1,31 @@
+#ifndef _HAIKU_BUILD_COMPATIBILITY_DARWIN_SYS_STAT
+#define _HAIKU_BUILD_COMPATIBILITY_DARWIN_SYS_STAT
+
+#include_next <sys/stat.h>
+
+#include <sys/cdefs.h>
+
+
+#ifndef UTIME_NOW
+#      define UTIME_NOW        (-1)
+#      define UTIME_OMIT       (-2)
+
+       __BEGIN_DECLS
+
+       /* assume that futimens() and utimensat() aren't available */
+       int     futimens(int fd, const struct timespec times[2]);
+       int utimensat(int fd, const char* path, const struct timespec times[2],
+               int flag);
+
+       __END_DECLS
+
+#      ifndef _HAIKU_BUILD_NO_FUTIMENS
+#              define _HAIKU_BUILD_NO_FUTIMENS         1
+#      endif
+#      ifndef _HAIKU_BUILD_NO_UTIMENSAT
+#              define _HAIKU_BUILD_NO_UTIMENSAT        1
+#      endif
+#endif
+
+
+#endif /* _HAIKU_BUILD_COMPATIBILITY_DARWIN_SYS_STAT */
\ No newline at end of file
diff --git a/src/build/libroot/Jamfile b/src/build/libroot/Jamfile
index 0104f25..f8cb92d 100644
--- a/src/build/libroot/Jamfile
+++ b/src/build/libroot/Jamfile
@@ -50,6 +50,10 @@ if $(HOST_PLATFORM) = freebsd {
        hostPlatformSources = fs_freebsd.cpp ;
 }
 
+if $(HOST_PLATFORM) = darwin {
+       hostPlatformSources = fs_darwin.cpp ;
+}
+
 local librootSources =
        atomic.cpp
        byteorder.cpp
diff --git a/src/build/libroot/fs.cpp b/src/build/libroot/fs.cpp
index 5de5bfa..13a0fdd 100644
--- a/src/build/libroot/fs.cpp
+++ b/src/build/libroot/fs.cpp
@@ -31,6 +31,8 @@
 
 #if defined(HAIKU_HOST_PLATFORM_FREEBSD)
 #      include "fs_freebsd.h"
+#elif defined(HAIKU_HOST_PLATFORM_DARWIN)
+#      include "fs_darwin.h"
 #endif
 
 
@@ -45,6 +47,13 @@ using namespace BPrivate;
 #      define haiku_host_platform_writev       haiku_freebsd_writev
 #      define HAIKU_HOST_STAT_ATIM(x)          ((x).st_atimespec)
 #      define HAIKU_HOST_STAT_MTIM(x)          ((x).st_mtimespec)
+#elif defined(HAIKU_HOST_PLATFORM_DARWIN)
+#      define haiku_host_platform_read         read
+#      define haiku_host_platform_write        write
+#      define haiku_host_platform_readv        readv
+#      define haiku_host_platform_writev       writev
+#      define HAIKU_HOST_STAT_ATIM(x)          ((x).st_atimespec)
+#      define HAIKU_HOST_STAT_MTIM(x)          ((x).st_mtimespec)
 #else
 #      define haiku_host_platform_read         read
 #      define haiku_host_platform_write        write
@@ -65,6 +74,129 @@ using namespace BPrivate;
        } while (0)
 
 
+#if defined(_HAIKU_BUILD_NO_FUTIMENS) || defined(_HAIKU_BUILD_NO_FUTIMENS)
+
+template<typename File>
+static int
+utimes_helper(File& file, const struct timespec times[2])
+{
+       if (times == NULL)
+               return file.SetTimes(NULL);
+
+       timeval timeBuffer[2];
+       timeBuffer[0].tv_sec = times[0].tv_sec;
+       timeBuffer[0].tv_usec = times[0].tv_nsec / 1000;
+       timeBuffer[1].tv_sec = times[1].tv_sec;
+       timeBuffer[1].tv_usec = times[1].tv_nsec / 1000;
+
+       if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) {
+               struct stat st;
+               if (file.GetStat(st) != 0)
+                       return -1;
+
+               if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == 
UTIME_OMIT)
+                       return 0;
+
+               if (times[0].tv_nsec == UTIME_OMIT) {
+                       timeBuffer[0].tv_sec = st.st_atimespec.tv_sec;
+                       timeBuffer[0].tv_usec = st.st_atimespec.tv_nsec / 1000;
+               }
+
+               if (times[1].tv_nsec == UTIME_OMIT) {
+                       timeBuffer[1].tv_sec = st.st_mtimespec.tv_sec;
+                       timeBuffer[1].tv_usec = st.st_mtimespec.tv_nsec / 1000;
+               }
+       }
+
+       if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) {
+               timeval now;
+               gettimeofday(&now, NULL);
+
+               if (times[0].tv_nsec == UTIME_NOW)
+                       timeBuffer[0] = now;
+
+               if (times[1].tv_nsec == UTIME_NOW)
+                       timeBuffer[1] = now;
+       }
+
+       return file.SetTimes(timeBuffer);       
+}
+
+#endif // _HAIKU_BUILD_NO_FUTIMENS || _HAIKU_BUILD_NO_FUTIMENS
+
+
+#ifdef _HAIKU_BUILD_NO_FUTIMENS
+
+struct FDFile {
+       FDFile(int fd)
+               :
+               fFD(fd)
+       {
+       }
+
+       int GetStat(struct stat& _st)
+       {
+               return fstat(fFD, &_st);
+       }
+
+       int SetTimes(const timeval times[2])
+       {
+               return futimes(fFD, times);
+       }
+
+private:
+       int fFD;
+};
+
+
+int
+futimens(int fd, const struct timespec times[2])
+{
+       FDFile file(fd);
+       return utimes_helper(file, times);
+}
+
+#endif // _HAIKU_BUILD_NO_FUTIMENS
+
+#ifdef _HAIKU_BUILD_NO_UTIMENSAT
+
+struct FDPathFile {
+       FDPathFile(int fd, const char* path, int flag)
+               :
+               fFD(fd),
+               fPath(path),
+               fFlag(flag)
+       {
+       }
+
+       int GetStat(struct stat& _st)
+       {
+               return fstatat(fFD, fPath, &_st, fFlag);
+       }
+
+       int SetTimes(const timeval times[2])
+       {
+               // TODO: fFlag (AT_SYMLINK_NOFOLLOW) is not supported here!
+               return futimesat(fFD, fPath, times);
+       }
+
+private:
+       int                     fFD;
+       const char*     fPath;
+       int                     fFlag;
+};
+
+
+int
+utimensat(int fd, const char* path, const struct timespec times[2], int flag)
+{
+       FDPathFile file(fd, path, flag);
+       return utimes_helper(file, times);
+}
+
+#endif // _HAIKU_BUILD_NO_UTIMENSAT
+
+
 static status_t get_path(dev_t device, ino_t node, const char *name,
        string &path);
 
diff --git a/src/build/libroot/fs_darwin.cpp b/src/build/libroot/fs_darwin.cpp
new file mode 100644
index 0000000..23f45e2
--- /dev/null
+++ b/src/build/libroot/fs_darwin.cpp
@@ -0,0 +1,659 @@
+/*
+ * Copyright 2011, John Scipione, jscipione@xxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "fs_darwin.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+
+int get_path(int fd, const char* path, char** fullPath);
+int eaccess(const char* path, int accessMode);
+
+
+int
+get_path(int fd, const char* path, char** fullPath)
+{
+       struct stat dirst;
+       if (fstat(fd, &dirst) < 0) {
+               // failed to grab stat information, fstat() sets errno
+               return -1;
+       }
+
+       if (!S_ISDIR(dirst.st_mode)) {
+               // fd does not point to a directory
+               errno = ENOTDIR;
+               return -1;
+       }
+
+       if (fcntl(fd, F_GETPATH, *fullPath) < 0) {
+               // failed to get the path of fd, fcntl() sets errno
+               return -1;
+       }
+
+       if (strlcat(*fullPath, "/", MAXPATHLEN) > MAXPATHLEN
+               || strlcat(*fullPath, path, MAXPATHLEN) > MAXPATHLEN) {
+               // full path is too long
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+}
+
+int
+eaccess(const char* path, int accessMode)
+{
+       uid_t uid = geteuid();
+       int fileMode = 0;
+
+       struct stat st;
+       if (stat(path, &st) < 0) {
+               // failed to get stat information on path, stat() sets errno
+               return -1;
+       }
+
+       if (uid == 0) {
+               // user is root
+               // root has always read/write permission, but at least one of 
the
+               // X bits must be set for execute permission
+               fileMode = R_OK | W_OK;
+               if ((st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)
+                       fileMode |= X_OK;
+       } else if (st.st_uid == uid) {
+               // user is node owner
+               if ((st.st_mode & S_IRUSR) != 0)
+                       fileMode |= R_OK;
+               if ((st.st_mode & S_IWUSR) != 0)
+                       fileMode |= W_OK;
+               if ((st.st_mode & S_IXUSR) != 0)
+                       fileMode |= X_OK;
+       } else if (st.st_gid == getegid()) {
+               // user is in owning group
+               if ((st.st_mode & S_IRGRP) != 0)
+                       fileMode |= R_OK;
+               if ((st.st_mode & S_IWGRP) != 0)
+                       fileMode |= W_OK;
+               if ((st.st_mode & S_IXGRP) != 0)
+                       fileMode |= X_OK;
+       } else {
+               // user is one of the others
+               if ((st.st_mode & S_IROTH) != 0)
+                       fileMode |= R_OK;
+               if ((st.st_mode & S_IWOTH) != 0)
+                       fileMode |= W_OK;
+               if ((st.st_mode & S_IXOTH) != 0)
+                       fileMode |= X_OK;
+       }
+
+       if ((accessMode & ~fileMode) != 0) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return 0;
+}
+
+
+int
+faccessat(int fd, const char* path, int accessMode, int flag)
+{
+       if (flag != AT_EACCESS && flag != 0) {
+               // invalid flag
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (fd == AT_FDCWD || path != NULL && path[0] == '/') {
+               // call access() ignoring fd
+               return (flag & AT_EACCESS) != 0 ? eaccess(path, accessMode)
+                       : access(path, accessMode);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *fullPath = (char *)malloc(MAXPATHLEN);
+       if (fullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, path, &fullPath) < 0) {
+               free(fullPath);
+               return -1;
+       }
+
+       int status = (flag & AT_EACCESS) != 0 ? eaccess(fullPath, accessMode)
+               : access(fullPath, accessMode);
+       free(fullPath);
+       return status;
+}
+
+
+int
+fchmodat(int fd, const char* path, mode_t mode, int flag)
+{
+       if ((flag & AT_SYMLINK_NOFOLLOW) == 0 && flag != 0) {
+               // invalid flag
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (fd == AT_FDCWD || path != NULL && path[0] == '/') {
+               // call chmod() ignoring fd
+               if ((flag & AT_SYMLINK_NOFOLLOW) != 0) {
+                       // fake lchmod() with open() and fchmod()
+                       int symlinkfd = open(path, O_RDONLY | O_SYMLINK);
+                       int status = fchmod(symlinkfd, mode);
+                       close(symlinkfd);
+                       return status;
+               } else
+                       return chmod(path, mode);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *fullPath = (char *)malloc(MAXPATHLEN);
+       if (fullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, path, &fullPath) < 0) {
+               free(fullPath);
+               return -1;
+       }
+
+       int status;
+
+       if ((flag & AT_SYMLINK_NOFOLLOW) != 0) {
+               // fake lchmod() with open() and fchmod()
+               int fullfd = open(fullPath, O_RDONLY | O_SYMLINK);
+               status = fchmod(fullfd, mode);
+               close(fullfd);
+       } else
+               status = chmod(fullPath, mode);
+
+       free(fullPath);
+       return status;
+}
+
+
+int
+fchownat(int fd, const char* path, uid_t owner, gid_t group, int flag)
+{
+       if ((flag & AT_SYMLINK_NOFOLLOW) == 0 && flag != 0) {
+               // invalid flag
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (fd == AT_FDCWD || path != NULL && path[0] == '/') {
+               // call chown() ignoring fd
+               return (flag & AT_SYMLINK_NOFOLLOW) != 0 ? lchown(path, owner, 
group)
+                       : chown(path, owner, group);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *fullPath = (char *)malloc(MAXPATHLEN);
+       if (fullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, path, &fullPath) < 0) {
+               free(fullPath);
+               return -1;
+       }
+
+       int status = (flag & AT_SYMLINK_NOFOLLOW) != 0
+               ? lchown(fullPath, owner, group) : chown(fullPath, owner, 
group);
+       free(fullPath);
+       return status;
+}
+
+
+int
+fstatat(int fd, const char *path, struct stat *st, int flag)
+{
+       if ((flag & AT_SYMLINK_NOFOLLOW) == 0 && flag != 0) {
+               // invalid flag
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (fd == AT_FDCWD || path != NULL && path[0] == '/') {
+               // call stat() or lstat() ignoring fd
+               return (flag & AT_SYMLINK_NOFOLLOW) != 0 ? lstat(path, st)
+                       : stat(path, st);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *fullPath = (char *)malloc(MAXPATHLEN);
+       if (fullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, path, &fullPath) < 0) {
+               free(fullPath);
+               return -1;
+       }
+
+       int status = (flag & AT_SYMLINK_NOFOLLOW) != 0 ? lstat(fullPath, st)
+               : stat(fullPath, st);
+       free(fullPath);
+       return status;
+}
+
+
+int
+mkdirat(int fd, const char *path, mode_t mode)
+{
+       if (fd == AT_FDCWD || path != NULL && path[0] == '/') {
+               // call mkdir() ignoring fd
+               return mkdir(path, mode);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *fullPath = (char *)malloc(MAXPATHLEN);
+       if (fullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, path, &fullPath) < 0) {
+               free(fullPath);
+               return -1;
+       }
+
+       int status = mkdir(fullPath, mode);
+       free(fullPath);
+       return status;
+}
+
+
+int
+mkfifoat(int fd, const char *path, mode_t mode)
+{
+       if (fd == AT_FDCWD || path != NULL && path[0] == '/') {
+               // call mkfifo() ignoring fd
+               return mkfifo(path, mode);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *fullPath = (char *)malloc(MAXPATHLEN);
+       if (fullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, path, &fullPath) < 0) {
+               free(fullPath);
+               return -1;
+       }
+
+       int status = mkfifo(fullPath, mode);
+       free(fullPath);
+       return status;
+}
+
+
+int
+mknodat(int fd, const char *path, mode_t mode, dev_t dev)
+{
+       if (fd == AT_FDCWD || path != NULL && path[0] == '/') {
+               // call mknod() ignoring fd
+               return mknod(path, mode, dev);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *fullPath = (char *)malloc(MAXPATHLEN);
+       if (fullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, path, &fullPath) < 0) {
+               free(fullPath);
+               return -1;
+       }
+
+       int status = mknod(fullPath, mode, dev);
+       free(fullPath);
+       return status;
+}
+
+
+int
+renameat(int oldFD, const char* oldPath, int newFD, const char* newPath)
+{
+       bool ignoreOldFD = false;
+       bool ignoreNewFD = false;
+
+       if (oldFD == AT_FDCWD || oldPath != NULL && oldPath[0] == '/')
+               ignoreOldFD = true;
+
+       if (newFD == AT_FDCWD || newPath != NULL && newPath[0] == '/')
+               ignoreNewFD = true;
+
+       if (ignoreOldFD && ignoreNewFD) {
+               // call rename() ignoring the fd's
+               return rename(oldPath, newPath);
+       }
+
+       char *oldFullPath;
+       char *newFullPath;
+
+       if (!ignoreOldFD) {
+               if (oldFD < 0) {
+                       // Invalid file descriptor
+                       errno = EBADF;
+                       return -1;
+               }
+
+               oldFullPath = (char *)malloc(MAXPATHLEN);
+               if (oldFullPath == NULL) {
+                       // ran out of memory allocating oldFullPath
+                       errno = ENOMEM;
+                       return -1;
+               }
+
+               if (get_path(oldFD, oldPath, &oldFullPath) < 0) {
+                       free(oldFullPath);
+                       return -1;
+               }
+       }
+
+       if (!ignoreNewFD) {
+               if (newFD < 0) {
+                       // Invalid file descriptor
+                       errno = EBADF;
+                       return -1;
+               }
+
+               newFullPath = (char *)malloc(MAXPATHLEN);
+               if (newFullPath == NULL) {
+                       // ran out of memory allocating newFullPath
+                       errno = ENOMEM;
+                       return -1;
+               }
+
+               if (get_path(newFD, newPath, &newFullPath) < 0) {
+                       free(newFullPath);
+                       return -1;
+               }
+       }
+
+       int status = rename(ignoreOldFD ? oldPath : oldFullPath,
+               ignoreNewFD ? newPath : newFullPath);
+       if (!ignoreOldFD)
+               free(oldFullPath);
+       if (!ignoreNewFD)
+               free(newFullPath);
+       return status;
+}
+
+
+ssize_t
+readlinkat(int fd, const char *path, char *buffer, size_t bufferSize)
+{
+       if (fd == AT_FDCWD || path != NULL && path[0] == '/') {
+               // call readlink() ignoring fd
+               return readlink(path, buffer, bufferSize);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *fullPath = (char *)malloc(MAXPATHLEN);
+       if (fullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, path, &fullPath) < 0) {
+               free(fullPath);
+               return -1;
+       }
+
+       int status = readlink(fullPath, buffer, bufferSize);
+       free(fullPath);
+       return status;
+}
+
+
+int
+symlinkat(const char *oldPath, int fd, const char *newPath)
+{
+       if (fd == AT_FDCWD || newPath != NULL && newPath[0] == '/') {
+               // call symlink() ignoring fd
+               return symlink(oldPath, newPath);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *oldFullPath = (char *)malloc(MAXPATHLEN);
+       if (oldFullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, oldPath, &oldFullPath) < 0) {
+               free(oldFullPath);
+               return -1;
+       }
+
+       int status = symlink(oldFullPath, newPath);
+       free(oldFullPath);
+       return status;
+}
+
+
+int
+unlinkat(int fd, const char *path, int flag)
+{
+       if ((flag & AT_REMOVEDIR) == 0 && flag != 0) {
+               // invalid flag
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (fd == AT_FDCWD || path != NULL && path[0] == '/') {
+               // call rmdir() or unlink() ignoring fd
+               return (flag & AT_REMOVEDIR) != 0 ? rmdir(path) : unlink(path);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *fullPath = (char *)malloc(MAXPATHLEN);
+       if (fullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, path, &fullPath) < 0) {
+               free(fullPath);
+               return -1;
+       }
+
+       int status = (flag & AT_REMOVEDIR) != 0 ? rmdir(fullPath)
+               : unlink(fullPath);
+       free(fullPath);
+       return status;
+}
+
+
+int
+linkat(int oldFD, const char *oldPath, int newFD, const char *newPath,
+          int flag)
+{
+       if ((flag & AT_SYMLINK_FOLLOW) != 0) {
+               // Dereference oldPath
+               // CURRENTLY UNSUPPORTED
+               errno = ENOTSUP;
+               return -1;
+       } else if (flag != 0) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       bool ignoreOldFD = false;
+       bool ignoreNewFD = false;
+
+       if (oldFD == AT_FDCWD || oldPath != NULL && oldPath[0] == '/')
+               ignoreOldFD = true;
+
+       if (newFD == AT_FDCWD || newPath != NULL && newPath[0] == '/')
+               ignoreNewFD = true;
+
+       if (ignoreOldFD && ignoreNewFD) {
+               // call link() ignoring the fd's
+               return link(oldPath, newPath);
+       }
+
+       char *oldFullPath;
+       char *newFullPath;
+
+       if (!ignoreOldFD) {
+               if (oldFD < 0) {
+                       // Invalid file descriptor
+                       errno = EBADF;
+                       return -1;
+               }
+
+               oldFullPath = (char *)malloc(MAXPATHLEN);
+               if (oldFullPath == NULL) {
+                       // ran out of memory allocating oldFullPath
+                       errno = ENOMEM;
+                       return -1;
+               }
+
+               if (get_path(oldFD, oldPath, &oldFullPath) < 0) {
+                       free(oldFullPath);
+                       return -1;
+               }
+       }
+
+       if (!ignoreNewFD) {
+               if (newFD < 0) {
+                       // Invalid file descriptor
+                       errno = EBADF;
+                       return -1;
+               }
+
+               newFullPath = (char *)malloc(MAXPATHLEN);
+               if (newFullPath == NULL) {
+                       // ran out of memory allocating newFullPath
+                       errno = ENOMEM;
+                       return -1;
+               }
+
+               if (get_path(newFD, newPath, &newFullPath) < 0) {
+                       free(newFullPath);
+                       return -1;
+               }
+       }
+
+       int status = link(ignoreOldFD ? oldPath : oldFullPath,
+               ignoreNewFD ? newPath : newFullPath);
+       if (!ignoreOldFD)
+               free(oldFullPath);
+       if (!ignoreNewFD)
+               free(newFullPath);
+       return status;
+}
+
+
+int
+futimesat(int fd, const char *path, const struct timeval times[2])
+{
+       if (fd == AT_FDCWD || path != NULL && path[0] == '/') {
+               // call utimes() ignoring fd
+               return utimes(path, times);
+       }
+
+       if (fd < 0) {
+               // Invalid file descriptor
+               errno = EBADF;
+               return -1;
+       }
+
+       char *fullPath = (char *)malloc(MAXPATHLEN);
+       if (fullPath == NULL) {
+               // ran out of memory allocating dirpath
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (get_path(fd, path, &fullPath) < 0) {
+               free(fullPath);
+               return -1;
+       }
+
+       int status = utimes(fullPath, times);
+       free(fullPath);
+       return status;
+}
diff --git a/src/build/libroot/fs_darwin.h b/src/build/libroot/fs_darwin.h
new file mode 100644
index 0000000..dbdd7c2
--- /dev/null
+++ b/src/build/libroot/fs_darwin.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011, John Scipione, jscipione@xxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef FS_DARWIN_H
+#define FS_DARWIN_H
+
+/*
+ * Magic value that specify the use of the current working directory
+ * to determine the target of relative file paths in the openat() and
+ * similar syscalls.
+ */
+#define AT_FDCWD                       -100    /* CWD FD for the *at() 
functions */
+
+/*
+ * Miscellaneous flags for the *at() syscalls.
+ */
+#define AT_EACCESS                     0x100   /* faccessat() */
+#define AT_SYMLINK_NOFOLLOW    0x200   /* fstatat(), fchmodat(), fchownat(),
+                                                                               
utimensat() */
+#define AT_SYMLINK_FOLLOW      0x400   /* linkat() */
+#define AT_REMOVEDIR           0x800   /* unlinkat() */
+
+int faccessat(int fd, const char* path, int accessMode, int flag);
+int fchmodat(int fd, const char* path, mode_t mode, int flag);
+int fchownat(int fd, const char* path, uid_t owner, gid_t group, int flag);
+int fstatat(int fd, const char *path, struct stat *st, int flag);
+int mkdirat(int fd, const char *path, mode_t mode);
+int mkfifoat(int fd, const char *path, mode_t mode);
+int mknodat(int fd, const char *name, mode_t mode, dev_t dev);
+int renameat(int oldFD, const char* oldPath, int newFD, const char* newPath);
+
+ssize_t readlinkat(int fd, const char *path, char *buffer, size_t bufferSize);
+int symlinkat(const char *oldPath, int fd, const char *newPath);
+int unlinkat(int fd, const char *path, int flag);
+int linkat(int oldFD, const char *oldPath, int newFD, const char *newPath,
+       int flag);
+
+int futimesat(int fd, const char *path, const struct timeval times[2]);
+
+#endif // FS_DARWIN_H
diff --git a/src/build/libroot/fs_freebsd.cpp b/src/build/libroot/fs_freebsd.cpp
index 339d8a5..648650e 100644
--- a/src/build/libroot/fs_freebsd.cpp
+++ b/src/build/libroot/fs_freebsd.cpp
@@ -254,127 +254,3 @@ haiku_freebsd_writev(int fd, const struct iovec *vecs, 
size_t count)
 
        return bytesWritten;
 }
-
-
-#if defined(_HAIKU_BUILD_NO_FUTIMENS) || defined(_HAIKU_BUILD_NO_FUTIMENS)
-
-template<typename File>
-static int
-utimes_helper(File& file, const struct timespec times[2])
-{
-       if (times == NULL)
-               return file.SetTimes(NULL);
-
-       timeval timeBuffer[2];
-       timeBuffer[0].tv_sec = times[0].tv_sec;
-       timeBuffer[0].tv_usec = times[0].tv_nsec / 1000;
-       timeBuffer[1].tv_sec = times[1].tv_sec;
-       timeBuffer[1].tv_usec = times[1].tv_nsec / 1000;
-
-       if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) {
-               struct stat st;
-               if (file.GetStat(st) != 0)
-                       return -1;
-
-               if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == 
UTIME_OMIT)
-                       return 0;
-
-               if (times[0].tv_nsec == UTIME_OMIT) {
-                       timeBuffer[0].tv_sec = st.st_atimespec.tv_sec;
-                       timeBuffer[0].tv_usec = st.st_atimespec.tv_nsec / 1000;
-               }
-
-               if (times[1].tv_nsec == UTIME_OMIT) {
-                       timeBuffer[1].tv_sec = st.st_mtimespec.tv_sec;
-                       timeBuffer[1].tv_usec = st.st_mtimespec.tv_nsec / 1000;
-               }
-       }
-
-       if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) {
-               timeval now;
-               gettimeofday(&now, NULL);
-
-               if (times[0].tv_nsec == UTIME_NOW)
-                       timeBuffer[0] = now;
-
-               if (times[1].tv_nsec == UTIME_NOW)
-                       timeBuffer[1] = now;
-       }
-
-       return file.SetTimes(timeBuffer);       
-}
-
-#endif // _HAIKU_BUILD_NO_FUTIMENS || _HAIKU_BUILD_NO_FUTIMENS
-
-
-#ifdef _HAIKU_BUILD_NO_FUTIMENS
-
-struct FDFile {
-       FDFile(int fd)
-               :
-               fFD(fd)
-       {
-       }
-
-       int GetStat(struct stat& _st)
-       {
-               return fstat(fFD, &_st);
-       }
-
-       int SetTimes(const timeval times[2])
-       {
-               return futimes(fFD, times);
-       }
-
-private:
-       int fFD;
-};
-
-
-int
-futimens(int fd, const struct timespec times[2])
-{
-       FDFile file(fd);
-       return utimes_helper(file, times);
-}
-
-#endif // _HAIKU_BUILD_NO_FUTIMENS
-
-
-#ifdef _HAIKU_BUILD_NO_UTIMENSAT
-
-struct FDPathFile {
-       FDPathFile(int fd, const char* path, int flag)
-               :
-               fFD(fd),
-               fPath(path),
-               fFlag(flag)
-       {
-       }
-
-       int GetStat(struct stat& _st)
-       {
-               return fstatat(fFD, fPath, &_st, fFlag);
-       }
-
-       int SetTimes(const timeval times[2])
-       {
-               // TODO: fFlag (AT_SYMLINK_NOFOLLOW) is not supported here!
-               return futimesat(fFD, fPath, times);
-       }
-
-private:
-       int                     fFD;
-       const char*     fPath;
-       int                     fFlag;
-};
-
-
-int
-utimensat(int fd, const char* path, const struct timespec times[2], int flag)
-{
-       FDPathFile file(fd, path, flag);
-       return utimes_helper(file, times);
-}
-
-#endif // _HAIKU_BUILD_NO_UTIMENSAT
diff --git a/src/system/libroot/os/driver_settings.cpp 
b/src/system/libroot/os/driver_settings.cpp
index b62bea0..8abe187 100644
--- a/src/system/libroot/os/driver_settings.cpp
+++ b/src/system/libroot/os/driver_settings.cpp
@@ -977,5 +977,5 @@ get_driver_settings(void *handle)
 // this creates an alias of the above function
 // unload_driver_settings() is the same as delete_driver_settings()
 extern "C" __typeof(unload_driver_settings) delete_driver_settings
-       __attribute__((alias ("unload_driver_settings")));
+       __attribute__((weak, alias ("unload_driver_settings")));
 


Other related posts: