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
This commit is contained in:
@@ -473,7 +473,7 @@ done
|
|||||||
|
|
||||||
# check for case-sensitive filesystem if on darwin
|
# check for case-sensitive filesystem if on darwin
|
||||||
if [ $HOST_PLATFORM = "darwin" ]; then
|
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
|
if [ $? != 0 ]; then
|
||||||
echo "You need a case-sensitive file-system to build Haiku."
|
echo "You need a case-sensitive file-system to build Haiku."
|
||||||
echo "Please see the following guide on how to set one up:"
|
echo "Please see the following guide on how to set one up:"
|
||||||
|
|||||||
@@ -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 */
|
||||||
@@ -50,6 +50,10 @@ if $(HOST_PLATFORM) = freebsd {
|
|||||||
hostPlatformSources = fs_freebsd.cpp ;
|
hostPlatformSources = fs_freebsd.cpp ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if $(HOST_PLATFORM) = darwin {
|
||||||
|
hostPlatformSources = fs_darwin.cpp ;
|
||||||
|
}
|
||||||
|
|
||||||
local librootSources =
|
local librootSources =
|
||||||
atomic.cpp
|
atomic.cpp
|
||||||
byteorder.cpp
|
byteorder.cpp
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
#if defined(HAIKU_HOST_PLATFORM_FREEBSD)
|
#if defined(HAIKU_HOST_PLATFORM_FREEBSD)
|
||||||
# include "fs_freebsd.h"
|
# include "fs_freebsd.h"
|
||||||
|
#elif defined(HAIKU_HOST_PLATFORM_DARWIN)
|
||||||
|
# include "fs_darwin.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -45,6 +47,13 @@ using namespace BPrivate;
|
|||||||
# define haiku_host_platform_writev haiku_freebsd_writev
|
# define haiku_host_platform_writev haiku_freebsd_writev
|
||||||
# define HAIKU_HOST_STAT_ATIM(x) ((x).st_atimespec)
|
# define HAIKU_HOST_STAT_ATIM(x) ((x).st_atimespec)
|
||||||
# define HAIKU_HOST_STAT_MTIM(x) ((x).st_mtimespec)
|
# 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
|
#else
|
||||||
# define haiku_host_platform_read read
|
# define haiku_host_platform_read read
|
||||||
# define haiku_host_platform_write write
|
# define haiku_host_platform_write write
|
||||||
@@ -65,6 +74,129 @@ using namespace BPrivate;
|
|||||||
} while (0)
|
} 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,
|
static status_t get_path(dev_t device, ino_t node, const char *name,
|
||||||
string &path);
|
string &path);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,659 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, John Scipione, [email protected].
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, John Scipione, [email protected].
|
||||||
|
* 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
|
||||||
@@ -254,127 +254,3 @@ haiku_freebsd_writev(int fd, const struct iovec *vecs, size_t count)
|
|||||||
|
|
||||||
return bytesWritten;
|
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
|
|
||||||
|
|||||||
@@ -977,5 +977,5 @@ get_driver_settings(void *handle)
|
|||||||
// this creates an alias of the above function
|
// this creates an alias of the above function
|
||||||
// unload_driver_settings() is the same as delete_driver_settings()
|
// unload_driver_settings() is the same as delete_driver_settings()
|
||||||
extern "C" __typeof(unload_driver_settings) delete_driver_settings
|
extern "C" __typeof(unload_driver_settings) delete_driver_settings
|
||||||
__attribute__((alias ("unload_driver_settings")));
|
__attribute__((weak, alias ("unload_driver_settings")));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user