Implemented POSIX.1-2008 functions unlinkat(), symlinkat(), mkdirat(),
utimensat(), and futimens(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34010 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -70,6 +70,7 @@
|
||||
#define AT_SYMLINK_NOFOLLOW 0x1 /* fstatat(), fchmodat(), fchownat(),
|
||||
utimensat() */
|
||||
#define AT_SYMLINK_FOLLOW 0x2 /* linkat() */
|
||||
#define AT_REMOVEDIR 0x04 /* unlinkat() */
|
||||
#endif
|
||||
|
||||
/* advisory file locking */
|
||||
|
||||
@@ -101,6 +101,10 @@ struct stat {
|
||||
#define DEFFILEMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
||||
/* default file mode, everyone can read/write */
|
||||
|
||||
/* special values for timespec::tv_nsec passed to utimensat(), futimens() */
|
||||
#define UTIME_NOW 1000000000
|
||||
#define UTIME_OMIT 1000000001
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -114,9 +118,18 @@ extern int lstat(const char *path, struct stat *st);
|
||||
extern int fstatat(int fd, const char *path, struct stat *st, int flag);
|
||||
#endif
|
||||
extern int mkdir(const char *path, mode_t mode);
|
||||
#ifdef B_ENABLE_INCOMPLETE_POSIX_AT_SUPPORT
|
||||
extern int mkdirat(int fd, const char *path, mode_t mode);
|
||||
#endif
|
||||
extern int mkfifo(const char *path, mode_t mode);
|
||||
extern mode_t umask(mode_t cmask);
|
||||
|
||||
#ifdef B_ENABLE_INCOMPLETE_POSIX_AT_SUPPORT
|
||||
extern int utimensat(int fd, const char *path,
|
||||
const struct timespec times[2], int flag);
|
||||
#endif
|
||||
extern int futimens(int fd, const struct timespec times[2]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -135,6 +135,9 @@ extern int dup2(int fd1, int fd2);
|
||||
extern int close(int fd);
|
||||
extern int link(const char *name, const char *new_name);
|
||||
extern int unlink(const char *name);
|
||||
#ifdef B_ENABLE_INCOMPLETE_POSIX_AT_SUPPORT
|
||||
extern int unlinkat(int fd, const char *path, int flag);
|
||||
#endif
|
||||
extern int rmdir(const char *path);
|
||||
|
||||
extern ssize_t readlink(const char *path, char *buffer, size_t bufferSize);
|
||||
@@ -142,7 +145,10 @@ extern ssize_t readlink(const char *path, char *buffer, size_t bufferSize);
|
||||
extern ssize_t readlinkat(int fd, const char *path, char *buffer,
|
||||
size_t bufferSize);
|
||||
#endif
|
||||
extern int symlink(const char *from, const char *to);
|
||||
extern int symlink(const char *toPath, const char *symlinkPath);
|
||||
#ifdef B_ENABLE_INCOMPLETE_POSIX_AT_SUPPORT
|
||||
extern int symlinkat(const char *toPath, int fd, const char *symlinkPath);
|
||||
#endif
|
||||
|
||||
extern int ftruncate(int fd, off_t newSize);
|
||||
extern int truncate(const char *path, off_t newSize);
|
||||
|
||||
@@ -4,25 +4,26 @@
|
||||
*/
|
||||
|
||||
|
||||
#define B_ENABLE_INCOMPLETE_POSIX_AT_SUPPORT 1
|
||||
// make the *at() functions and AT_* macros visible
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <syscalls.h>
|
||||
#include <syscall_utils.h>
|
||||
#include <umask.h>
|
||||
|
||||
|
||||
#define RETURN_AND_SET_ERRNO(err) \
|
||||
if (err < 0) { \
|
||||
errno = err; \
|
||||
return -1; \
|
||||
} \
|
||||
return err;
|
||||
|
||||
|
||||
int
|
||||
mkdir(const char* path, mode_t mode)
|
||||
{
|
||||
status_t status = _kern_create_dir(-1, path, mode & ~__gUmask);
|
||||
|
||||
RETURN_AND_SET_ERRNO(status);
|
||||
RETURN_AND_SET_ERRNO(_kern_create_dir(-1, path, mode & ~__gUmask));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mkdirat(int fd, const char *path, mode_t mode)
|
||||
{
|
||||
RETURN_AND_SET_ERRNO(_kern_create_dir(fd, path, mode & ~__gUmask));
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2006-2009, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#define B_ENABLE_INCOMPLETE_POSIX_AT_SUPPORT 1
|
||||
// make the *at() functions and AT_* macros visible
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <errno.h>
|
||||
@@ -11,14 +15,7 @@
|
||||
#include <NodeMonitor.h>
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
|
||||
#define RETURN_AND_SET_ERRNO(err) \
|
||||
if (err < 0) { \
|
||||
errno = err; \
|
||||
return -1; \
|
||||
} \
|
||||
return err;
|
||||
#include <syscall_utils.h>
|
||||
|
||||
|
||||
int
|
||||
@@ -45,3 +42,60 @@ utimes(const char* path, const struct timeval times[2])
|
||||
RETURN_AND_SET_ERRNO(status);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
utimensat(int fd, const char *path, const struct timespec times[2], int flag)
|
||||
{
|
||||
struct stat stat;
|
||||
status_t status;
|
||||
uint32 mask = 0;
|
||||
|
||||
// Init the stat time fields to the current time, if at least one time is
|
||||
// supposed to be set to it.
|
||||
if (times == NULL || times[0].tv_nsec == UTIME_NOW
|
||||
|| times[1].tv_nsec == UTIME_NOW) {
|
||||
bigtime_t now = real_time_clock_usecs();
|
||||
stat.st_atim.tv_sec = stat.st_mtim.tv_sec = now / 1000000;
|
||||
stat.st_atim.tv_nsec = stat.st_mtim.tv_nsec = (now % 1000000) * 1000;
|
||||
}
|
||||
|
||||
if (times != NULL) {
|
||||
// access time
|
||||
if (times[0].tv_nsec != UTIME_OMIT) {
|
||||
mask |= B_STAT_ACCESS_TIME;
|
||||
|
||||
if (times[0].tv_nsec != UTIME_NOW) {
|
||||
if (times[0].tv_nsec < 0 || times[0].tv_nsec > 999999999)
|
||||
RETURN_AND_SET_ERRNO(EINVAL);
|
||||
}
|
||||
|
||||
stat.st_atim = times[0];
|
||||
}
|
||||
|
||||
// modified time
|
||||
if (times[1].tv_nsec != UTIME_OMIT) {
|
||||
mask |= B_STAT_MODIFICATION_TIME;
|
||||
|
||||
if (times[1].tv_nsec != UTIME_NOW) {
|
||||
if (times[1].tv_nsec < 0 || times[1].tv_nsec > 999999999)
|
||||
RETURN_AND_SET_ERRNO(EINVAL);
|
||||
}
|
||||
|
||||
stat.st_mtim = times[1];
|
||||
}
|
||||
}
|
||||
|
||||
// set the times -- as per spec we even need to do this, if both have
|
||||
// UTIME_OMIT set
|
||||
status = _kern_write_stat(fd, path, (flag & AT_SYMLINK_NOFOLLOW) != 0,
|
||||
&stat, sizeof(struct stat), mask);
|
||||
|
||||
RETURN_AND_SET_ERRNO(status);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
futimens(int fd, const struct timespec times[2])
|
||||
{
|
||||
return utimensat(fd, NULL, times, 0);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
SubDir HAIKU_TOP src system libroot posix unistd ;
|
||||
|
||||
UsePrivateSystemHeaders ;
|
||||
UsePrivateHeaders libroot runtime_loader ;
|
||||
UsePrivateHeaders libroot runtime_loader shared ;
|
||||
|
||||
MergeObject posix_unistd.o :
|
||||
access.c
|
||||
|
||||
@@ -10,14 +10,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <syscalls.h>
|
||||
|
||||
|
||||
#define RETURN_AND_SET_ERRNO(err) \
|
||||
if (err < 0) { \
|
||||
errno = err; \
|
||||
return -1; \
|
||||
} \
|
||||
return err;
|
||||
#include <syscall_utils.h>
|
||||
|
||||
|
||||
ssize_t
|
||||
@@ -55,6 +48,13 @@ symlink(const char *toPath, const char *symlinkPath)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
symlinkat(const char *toPath, int fd, const char *symlinkPath)
|
||||
{
|
||||
RETURN_AND_SET_ERRNO(_kern_create_symlink(fd, symlinkPath, toPath, 0));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
unlink(const char *path)
|
||||
{
|
||||
@@ -64,6 +64,16 @@ unlink(const char *path)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
unlinkat(int fd, const char *path, int flag)
|
||||
{
|
||||
if ((flag & AT_REMOVEDIR) != 0)
|
||||
RETURN_AND_SET_ERRNO(_kern_remove_dir(fd, path));
|
||||
else
|
||||
RETURN_AND_SET_ERRNO(_kern_unlink(fd, path));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
link(const char *toPath, const char *linkPath)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user