diff options
author | Rich Felker <dalias@aerifal.cx> | 2014-05-29 21:01:32 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2014-05-29 21:01:32 -0400 |
commit | dd5f50da6f6c3df5647e922e47f8568a8896a752 (patch) | |
tree | c5ab9a1006d2ab4c449f8fa922ce3237acad30e4 /src/stat | |
parent | 2e55da911896a91e95b24ab5dc8a9d9b0718f4de (diff) | |
download | musl-dd5f50da6f6c3df5647e922e47f8568a8896a752.tar.gz musl-dd5f50da6f6c3df5647e922e47f8568a8896a752.tar.bz2 musl-dd5f50da6f6c3df5647e922e47f8568a8896a752.tar.xz musl-dd5f50da6f6c3df5647e922e47f8568a8896a752.zip |
support linux kernel apis (new archs) with old syscalls removed
such archs are expected to omit definitions of the SYS_* macros for
syscalls their kernels lack from arch/$ARCH/bits/syscall.h. the
preprocessor is then able to select the an appropriate implementation
for affected functions. two basic strategies are used on a
case-by-case basis:
where the old syscalls correspond to deprecated library-level
functions, the deprecated functions have been converted to wrappers
for the modern function, and the modern function has fallback code
(omitted at the preprocessor level on new archs) to make use of the
old syscalls if the new syscall fails with ENOSYS. this also improves
functionality on older kernels and eliminates the incentive to program
with deprecated library-level functions for the sake of compatibility
with older kernels.
in other situations where the old syscalls correspond to library-level
functions which are not deprecated but merely lack some new features,
such as the *at functions, the old syscalls are still used on archs
which support them. this may change at some point in the future if or
when fallback code is added to the new functions to make them usable
(possibly with reduced functionality) on old kernels.
Diffstat (limited to 'src/stat')
-rw-r--r-- | src/stat/chmod.c | 5 | ||||
-rw-r--r-- | src/stat/fchmod.c | 4 | ||||
-rw-r--r-- | src/stat/fchmodat.c | 5 | ||||
-rw-r--r-- | src/stat/futimesat.c | 21 | ||||
-rw-r--r-- | src/stat/lstat.c | 5 | ||||
-rw-r--r-- | src/stat/mkdir.c | 5 | ||||
-rw-r--r-- | src/stat/mknod.c | 5 | ||||
-rw-r--r-- | src/stat/stat.c | 5 | ||||
-rw-r--r-- | src/stat/utimensat.c | 32 |
9 files changed, 80 insertions, 7 deletions
diff --git a/src/stat/chmod.c b/src/stat/chmod.c index beb66e59..d4f53c56 100644 --- a/src/stat/chmod.c +++ b/src/stat/chmod.c @@ -1,7 +1,12 @@ #include <sys/stat.h> +#include <fcntl.h> #include "syscall.h" int chmod(const char *path, mode_t mode) { +#ifdef SYS_chmod return syscall(SYS_chmod, path, mode); +#else + return syscall(SYS_fchmodat, AT_FDCWD, path, mode); +#endif } diff --git a/src/stat/fchmod.c b/src/stat/fchmod.c index 6d281416..93e1b64c 100644 --- a/src/stat/fchmod.c +++ b/src/stat/fchmod.c @@ -13,5 +13,9 @@ int fchmod(int fd, mode_t mode) char buf[15+3*sizeof(int)]; __procfdname(buf, fd); +#ifdef SYS_chmod return syscall(SYS_chmod, buf, mode); +#else + return syscall(SYS_fchmodat, AT_FDCWD, buf, mode); +#endif } diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c index 12e7ff0c..afa6d44b 100644 --- a/src/stat/fchmodat.c +++ b/src/stat/fchmodat.c @@ -28,8 +28,9 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) } __procfdname(proc, fd2); - if (!(ret = __syscall(SYS_stat, proc, &st)) && !S_ISLNK(st.st_mode)) - ret = __syscall(SYS_chmod, proc, mode); + ret = __syscall(SYS_fstatat, AT_FDCWD, proc, &st, 0); + if (!ret && !S_ISLNK(st.st_mode)) + ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode); __syscall(SYS_close, fd2); return __syscall_ret(ret); diff --git a/src/stat/futimesat.c b/src/stat/futimesat.c index dbefc844..b4eea1d3 100644 --- a/src/stat/futimesat.c +++ b/src/stat/futimesat.c @@ -1,10 +1,23 @@ #define _GNU_SOURCE #include <sys/time.h> +#include <sys/stat.h> +#include <errno.h> #include "syscall.h" +#include "libc.h" -#ifdef SYS_futimesat -int futimesat(int dirfd, const char *pathname, const struct timeval times[2]) +int __futimesat(int dirfd, const char *pathname, const struct timeval times[2]) { - return syscall(SYS_futimesat, dirfd, pathname, times); + struct timespec ts[2]; + if (times) { + int i; + for (i=0; i<2; i++) { + if (times[i].tv_usec >= 1000000ULL) + return __syscall_ret(-EINVAL); + ts[i].tv_sec = times[i].tv_sec; + ts[i].tv_nsec = times[i].tv_usec * 1000; + } + } + return utimensat(dirfd, pathname, times ? ts : 0, 0); } -#endif + +weak_alias(__futimesat, futimesat); diff --git a/src/stat/lstat.c b/src/stat/lstat.c index 8f60358c..5e8b84fc 100644 --- a/src/stat/lstat.c +++ b/src/stat/lstat.c @@ -1,10 +1,15 @@ #include <sys/stat.h> +#include <fcntl.h> #include "syscall.h" #include "libc.h" int lstat(const char *restrict path, struct stat *restrict buf) { +#ifdef SYS_lstat return syscall(SYS_lstat, path, buf); +#else + return syscall(SYS_fstatat, AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW); +#endif } LFS64(lstat); diff --git a/src/stat/mkdir.c b/src/stat/mkdir.c index 770e1ccc..32625b7d 100644 --- a/src/stat/mkdir.c +++ b/src/stat/mkdir.c @@ -1,7 +1,12 @@ #include <sys/stat.h> +#include <fcntl.h> #include "syscall.h" int mkdir(const char *path, mode_t mode) { +#ifdef SYS_mkdir return syscall(SYS_mkdir, path, mode); +#else + return syscall(SYS_mkdirat, AT_FDCWD, path, mode); +#endif } diff --git a/src/stat/mknod.c b/src/stat/mknod.c index c3196571..beebd84e 100644 --- a/src/stat/mknod.c +++ b/src/stat/mknod.c @@ -1,7 +1,12 @@ #include <sys/stat.h> +#include <fcntl.h> #include "syscall.h" int mknod(const char *path, mode_t mode, dev_t dev) { +#ifdef SYS_mknod return syscall(SYS_mknod, path, mode, dev); +#else + return syscall(SYS_mknodat, AT_FDCWD, path, mode, dev); +#endif } diff --git a/src/stat/stat.c b/src/stat/stat.c index c6de7168..b4433a0a 100644 --- a/src/stat/stat.c +++ b/src/stat/stat.c @@ -1,10 +1,15 @@ #include <sys/stat.h> +#include <fcntl.h> #include "syscall.h" #include "libc.h" int stat(const char *restrict path, struct stat *restrict buf) { +#ifdef SYS_stat return syscall(SYS_stat, path, buf); +#else + return syscall(SYS_fstatat, AT_FDCWD, path, buf, 0); +#endif } LFS64(stat); diff --git a/src/stat/utimensat.c b/src/stat/utimensat.c index 929698bc..159c8be3 100644 --- a/src/stat/utimensat.c +++ b/src/stat/utimensat.c @@ -1,7 +1,37 @@ #include <sys/stat.h> +#include <sys/time.h> +#include <fcntl.h> +#include <errno.h> #include "syscall.h" int utimensat(int fd, const char *path, const struct timespec times[2], int flags) { - return syscall(SYS_utimensat, fd, path, times, flags); + int r = __syscall(SYS_utimensat, fd, path, times, flags); +#ifdef SYS_futimesat + if (r != -ENOSYS || flags) return __syscall_ret(r); + struct timeval *tv = 0, tmp[2]; + if (times) { + int i; + tv = tmp; + for (i=0; i<2; i++) { + if (times[i].tv_nsec >= 1000000000ULL) { + if (times[i].tv_nsec == UTIME_NOW && + times[1-i].tv_nsec == UTIME_NOW) { + tv = 0; + break; + } + if (times[i].tv_nsec == UTIME_OMIT) + return __syscall_ret(-ENOSYS); + return __syscall_ret(-EINVAL); + } + tmp[i].tv_sec = times[i].tv_sec; + tmp[i].tv_usec = times[i].tv_nsec / 1000; + } + } + + r = __syscall(SYS_futimesat, fd, path, tv); + if (r != -ENOSYS || fd != AT_FDCWD) return __syscall_ret(r); + r = __syscall(SYS_utimes, path, tv); +#endif + return __syscall_ret(r); } |