mirror of https://git.musl-libc.org/git/musl
Browse Source
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.master
39 changed files with 267 additions and 29 deletions
@ -1,7 +1,10 @@ |
|||
#include <sys/time.h> |
|||
#include "fcntl.h" |
|||
#include "syscall.h" |
|||
|
|||
int __futimesat(int, const char *, const struct timeval [2]); |
|||
|
|||
int utimes(const char *path, const struct timeval times[2]) |
|||
{ |
|||
return syscall(SYS_utimes, path, times); |
|||
return __futimesat(AT_FDCWD, path, times); |
|||
} |
|||
|
|||
@ -1,8 +1,16 @@ |
|||
#include <poll.h> |
|||
#include <time.h> |
|||
#include <signal.h> |
|||
#include "syscall.h" |
|||
#include "libc.h" |
|||
|
|||
int poll(struct pollfd *fds, nfds_t n, int timeout) |
|||
{ |
|||
#ifdef SYS_poll |
|||
return syscall_cp(SYS_poll, fds, n, timeout); |
|||
#else |
|||
return syscall_cp(SYS_ppoll, fds, n, timeout>=0 ? |
|||
&((struct timespec){ .tv_sec = timeout/1000, |
|||
.tv_nsec = timeout%1000*1000000 }) : 0, 0, _NSIG/8); |
|||
#endif |
|||
} |
|||
|
|||
@ -1,8 +1,26 @@ |
|||
#include <sys/select.h> |
|||
#include <signal.h> |
|||
#include <stdint.h> |
|||
#include <errno.h> |
|||
#include "syscall.h" |
|||
#include "libc.h" |
|||
|
|||
int select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval *restrict tv) |
|||
{ |
|||
#ifdef SYS_select |
|||
return syscall_cp(SYS_select, n, rfds, wfds, efds, tv); |
|||
#else |
|||
syscall_arg_t data[2] = { 0, _NSIG/8 }; |
|||
struct timespec ts; |
|||
if (tv) { |
|||
if (tv->tv_sec < 0 || tv->tv_usec < 0) |
|||
return __syscall_ret(-EINVAL); |
|||
time_t extra_secs = tv->tv_usec / 1000000; |
|||
ts.tv_nsec = tv->tv_usec % 1000000 * 1000; |
|||
const time_t max_time = (1ULL<<8*sizeof(time_t)-1)-1; |
|||
ts.tv_sec = extra_secs > max_time - tv->tv_sec ? |
|||
max_time : tv->tv_sec + extra_secs; |
|||
} |
|||
return syscall_cp(SYS_pselect6, n, rfds, wfds, efds, tv ? &ts : 0, data); |
|||
#endif |
|||
} |
|||
|
|||
@ -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 |
|||
} |
|||
|
|||
@ -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; |
|||
} |
|||
#endif |
|||
} |
|||
return utimensat(dirfd, pathname, times ? ts : 0, 0); |
|||
} |
|||
|
|||
weak_alias(__futimesat, futimesat); |
|||
|
|||
@ -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); |
|||
|
|||
@ -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 |
|||
} |
|||
|
|||
@ -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 |
|||
} |
|||
|
|||
@ -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); |
|||
|
|||
@ -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); |
|||
} |
|||
|
|||
@ -1,9 +1,19 @@ |
|||
#include <stdio.h> |
|||
#include <errno.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
int remove(const char *path) |
|||
{ |
|||
int r = syscall(SYS_unlink, path); |
|||
return (r && errno == EISDIR) ? syscall(SYS_rmdir, path) : r; |
|||
#ifdef SYS_unlink |
|||
int r = __syscall(SYS_unlink, path); |
|||
#else |
|||
int r = __syscall(SYS_unlinkat, AT_FDCWD, path, 0); |
|||
#endif |
|||
#ifdef SYS_rmdir |
|||
if (r==-EISDIR) r = __syscall(SYS_rmdir, path); |
|||
#else |
|||
if (r==-EISDIR) r = __syscall(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); |
|||
#endif |
|||
return __syscall_ret(r); |
|||
} |
|||
|
|||
@ -1,7 +1,12 @@ |
|||
#include <stdio.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
int rename(const char *old, const char *new) |
|||
{ |
|||
#ifdef SYS_rename |
|||
return syscall(SYS_rename, old, new); |
|||
#else |
|||
return syscall(SYS_renameat, AT_FDCWD, old, AT_FDCWD, new); |
|||
#endif |
|||
} |
|||
|
|||
@ -1,14 +1,11 @@ |
|||
#include <utime.h> |
|||
#include <sys/time.h> |
|||
#include "syscall.h" |
|||
#include <sys/stat.h> |
|||
#include <time.h> |
|||
#include <fcntl.h> |
|||
|
|||
int utime(const char *path, const struct utimbuf *times) |
|||
{ |
|||
if (times) { |
|||
struct timeval tv[2] = { |
|||
{ .tv_sec = times->actime }, |
|||
{ .tv_sec = times->modtime } }; |
|||
return syscall(SYS_utimes, path, tv); |
|||
} |
|||
return syscall(SYS_utimes, path, 0); |
|||
return utimensat(AT_FDCWD, path, times ? ((struct timespec [2]){ |
|||
{ .tv_sec = times->actime }, { .tv_sec = times->modtime }}) |
|||
: 0, 0); |
|||
} |
|||
|
|||
@ -1,7 +1,12 @@ |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
int access(const char *filename, int amode) |
|||
{ |
|||
#ifdef SYS_access |
|||
return syscall(SYS_access, filename, amode); |
|||
#else |
|||
return syscall(SYS_faccessat, AT_FDCWD, filename, amode, 0); |
|||
#endif |
|||
} |
|||
|
|||
@ -1,7 +1,12 @@ |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
int chown(const char *path, uid_t uid, gid_t gid) |
|||
{ |
|||
#ifdef SYS_chown |
|||
return syscall(SYS_chown, path, uid, gid); |
|||
#else |
|||
return syscall(SYS_fchownat, AT_FDCWD, path, uid, gid, 0); |
|||
#endif |
|||
} |
|||
|
|||
@ -1,10 +1,20 @@ |
|||
#include <unistd.h> |
|||
#include <errno.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
int dup2(int old, int new) |
|||
{ |
|||
int r; |
|||
#ifdef SYS_dup2 |
|||
while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); |
|||
#else |
|||
if (old==new) { |
|||
r = __syscall(SYS_fcntl, old, F_GETFD); |
|||
if (r >= 0) return old; |
|||
} else { |
|||
while ((r=__syscall(SYS_dup3, old, new, 0))==-EBUSY); |
|||
} |
|||
#endif |
|||
return __syscall_ret(r); |
|||
} |
|||
|
|||
@ -1,7 +1,12 @@ |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
int lchown(const char *path, uid_t uid, gid_t gid) |
|||
{ |
|||
#ifdef SYS_lchown |
|||
return syscall(SYS_lchown, path, uid, gid); |
|||
#else |
|||
return syscall(SYS_fchownat, AT_FDCWD, path, uid, gid, AT_SYMLINK_NOFOLLOW); |
|||
#endif |
|||
} |
|||
|
|||
@ -1,7 +1,12 @@ |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
int link(const char *existing, const char *new) |
|||
{ |
|||
#ifdef SYS_link |
|||
return syscall(SYS_link, existing, new); |
|||
#else |
|||
return syscall(SYS_linkat, AT_FDCWD, existing, AT_FDCWD, new, 0); |
|||
#endif |
|||
} |
|||
|
|||
@ -1,8 +1,13 @@ |
|||
#include <unistd.h> |
|||
#include <signal.h> |
|||
#include "syscall.h" |
|||
#include "libc.h" |
|||
|
|||
int pause(void) |
|||
{ |
|||
#ifdef SYS_pause |
|||
return syscall_cp(SYS_pause); |
|||
#else |
|||
return syscall_cp(SYS_ppoll, 0, 0, 0, 0); |
|||
#endif |
|||
} |
|||
|
|||
@ -1,7 +1,12 @@ |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize) |
|||
{ |
|||
#ifdef SYS_readlink |
|||
return syscall(SYS_readlink, path, buf, bufsize); |
|||
#else |
|||
return syscall(SYS_readlinkat, AT_FDCWD, path, buf, bufsize); |
|||
#endif |
|||
} |
|||
|
|||
@ -1,7 +1,12 @@ |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
int rmdir(const char *path) |
|||
{ |
|||
#ifdef SYS_rmdir |
|||
return syscall(SYS_rmdir, path); |
|||
#else |
|||
return syscall(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); |
|||
#endif |
|||
} |
|||
|
|||
@ -1,7 +1,12 @@ |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
int symlink(const char *existing, const char *new) |
|||
{ |
|||
#ifdef SYS_symlink |
|||
return syscall(SYS_symlink, existing, new); |
|||
#else |
|||
return syscall(SYS_symlinkat, existing, AT_FDCWD, new); |
|||
#endif |
|||
} |
|||
|
|||
@ -1,7 +1,12 @@ |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "syscall.h" |
|||
|
|||
int unlink(const char *path) |
|||
{ |
|||
#ifdef SYS_unlink |
|||
return syscall(SYS_unlink, path); |
|||
#else |
|||
return syscall(SYS_unlinkat, AT_FDCWD, path, 0); |
|||
#endif |
|||
} |
|||
|
|||
Loading…
Reference in new issue