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(),
|
#define AT_SYMLINK_NOFOLLOW 0x1 /* fstatat(), fchmodat(), fchownat(),
|
||||||
utimensat() */
|
utimensat() */
|
||||||
#define AT_SYMLINK_FOLLOW 0x2 /* linkat() */
|
#define AT_SYMLINK_FOLLOW 0x2 /* linkat() */
|
||||||
|
#define AT_REMOVEDIR 0x04 /* unlinkat() */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* advisory file locking */
|
/* advisory file locking */
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ struct stat {
|
|||||||
#define DEFFILEMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
#define DEFFILEMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
||||||
/* default file mode, everyone can read/write */
|
/* 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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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);
|
extern int fstatat(int fd, const char *path, struct stat *st, int flag);
|
||||||
#endif
|
#endif
|
||||||
extern int mkdir(const char *path, mode_t mode);
|
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 int mkfifo(const char *path, mode_t mode);
|
||||||
extern mode_t umask(mode_t cmask);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ extern int dup2(int fd1, int fd2);
|
|||||||
extern int close(int fd);
|
extern int close(int fd);
|
||||||
extern int link(const char *name, const char *new_name);
|
extern int link(const char *name, const char *new_name);
|
||||||
extern int unlink(const char *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 int rmdir(const char *path);
|
||||||
|
|
||||||
extern ssize_t readlink(const char *path, char *buffer, size_t bufferSize);
|
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,
|
extern ssize_t readlinkat(int fd, const char *path, char *buffer,
|
||||||
size_t bufferSize);
|
size_t bufferSize);
|
||||||
#endif
|
#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 ftruncate(int fd, off_t newSize);
|
||||||
extern int truncate(const char *path, 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 <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
#include <syscall_utils.h>
|
||||||
#include <umask.h>
|
#include <umask.h>
|
||||||
|
|
||||||
|
|
||||||
#define RETURN_AND_SET_ERRNO(err) \
|
|
||||||
if (err < 0) { \
|
|
||||||
errno = err; \
|
|
||||||
return -1; \
|
|
||||||
} \
|
|
||||||
return err;
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
mkdir(const char* path, mode_t mode)
|
mkdir(const char* path, mode_t mode)
|
||||||
{
|
{
|
||||||
status_t status = _kern_create_dir(-1, path, mode & ~__gUmask);
|
RETURN_AND_SET_ERRNO(_kern_create_dir(-1, path, mode & ~__gUmask));
|
||||||
|
}
|
||||||
RETURN_AND_SET_ERRNO(status);
|
|
||||||
|
|
||||||
|
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].
|
* Copyright 2006-2009, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* 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 <sys/time.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -11,14 +15,7 @@
|
|||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
|
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
#include <syscall_utils.h>
|
||||||
|
|
||||||
#define RETURN_AND_SET_ERRNO(err) \
|
|
||||||
if (err < 0) { \
|
|
||||||
errno = err; \
|
|
||||||
return -1; \
|
|
||||||
} \
|
|
||||||
return err;
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -45,3 +42,60 @@ utimes(const char* path, const struct timeval times[2])
|
|||||||
RETURN_AND_SET_ERRNO(status);
|
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 ;
|
SubDir HAIKU_TOP src system libroot posix unistd ;
|
||||||
|
|
||||||
UsePrivateSystemHeaders ;
|
UsePrivateSystemHeaders ;
|
||||||
UsePrivateHeaders libroot runtime_loader ;
|
UsePrivateHeaders libroot runtime_loader shared ;
|
||||||
|
|
||||||
MergeObject posix_unistd.o :
|
MergeObject posix_unistd.o :
|
||||||
access.c
|
access.c
|
||||||
|
|||||||
@@ -10,14 +10,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
#include <syscall_utils.h>
|
||||||
|
|
||||||
#define RETURN_AND_SET_ERRNO(err) \
|
|
||||||
if (err < 0) { \
|
|
||||||
errno = err; \
|
|
||||||
return -1; \
|
|
||||||
} \
|
|
||||||
return err;
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
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
|
int
|
||||||
unlink(const char *path)
|
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
|
int
|
||||||
link(const char *toPath, const char *linkPath)
|
link(const char *toPath, const char *linkPath)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user