diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c index d7481c2..c10a3f3 100644 --- a/src/env/__libc_start_main.c +++ b/src/env/__libc_start_main.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "syscall.h" #include "atomic.h" #include "libc.h" @@ -48,7 +49,11 @@ void __init_libc(char **envp, char *pn) && !aux[AT_SECURE]) return; struct pollfd pfd[3] = { {.fd=0}, {.fd=1}, {.fd=2} }; +#ifdef SYS_poll __syscall(SYS_poll, pfd, 3, 0); +#else + __syscall(SYS_ppoll, pfd, 3, &(struct timespec){0}, 0, _NSIG/8); +#endif for (i=0; i<3; i++) if (pfd[i].revents&POLLNVAL) if (__sys_open("/dev/null", O_RDWR)<0) a_crash(); diff --git a/src/linux/utimes.c b/src/linux/utimes.c index 70c0695..b814c88 100644 --- a/src/linux/utimes.c +++ b/src/linux/utimes.c @@ -1,7 +1,10 @@ #include +#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); } diff --git a/src/process/fork.c b/src/process/fork.c index 864c7d7..89b04c6 100644 --- a/src/process/fork.c +++ b/src/process/fork.c @@ -1,5 +1,6 @@ #include #include +#include #include "syscall.h" #include "libc.h" #include "pthread_impl.h" @@ -16,7 +17,11 @@ pid_t fork(void) sigset_t set; __fork_handler(-1); __block_all_sigs(&set); +#ifdef SYS_fork ret = syscall(SYS_fork); +#else + ret = syscall(SYS_clone, SIGCHLD); +#endif if (libc.has_thread_pointer && !ret) { pthread_t self = __pthread_self(); self->tid = self->pid = __syscall(SYS_getpid); diff --git a/src/process/posix_spawn.c b/src/process/posix_spawn.c index 08644f5..6fa33cb 100644 --- a/src/process/posix_spawn.c +++ b/src/process/posix_spawn.c @@ -22,6 +22,18 @@ struct args { void __get_handler_set(sigset_t *); +static int do_dup2(int old, int new) +{ + int r; +#ifdef SYS_dup2 + while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); +#else + while ((r=__syscall(SYS_dup3, old, new, 0))==-EBUSY); + if (r==-EINVAL && old==new) return new; +#endif + return r; +} + static int child(void *args_vp) { int i, ret; @@ -92,14 +104,14 @@ static int child(void *args_vp) goto fail; break; case FDOP_DUP2: - if ((ret=__syscall(SYS_dup2, op->srcfd, op->fd))<0) + if ((ret=do_dup2(op->srcfd, op->fd))<0) goto fail; break; case FDOP_OPEN: fd = __sys_open(op->path, op->oflag, op->mode); if ((ret=fd) < 0) goto fail; if (fd != op->fd) { - if ((ret=__syscall(SYS_dup2, fd, op->fd))<0) + if ((ret=do_dup2(fd, op->fd))<0) goto fail; __syscall(SYS_close, fd); } diff --git a/src/select/poll.c b/src/select/poll.c index f1e73e8..f756643 100644 --- a/src/select/poll.c +++ b/src/select/poll.c @@ -4,5 +4,11 @@ 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 } diff --git a/src/select/select.c b/src/select/select.c index f93597b..cbff8c0 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -4,5 +4,16 @@ 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 + long data[2] = { 0, _NSIG/8 }; + struct timespec ts; + if (tv) { + ts.tv_sec = tv->tv_sec; + ts.tv_nsec = tv->tv_usec > 999999 ? + 999999999 : tv->tv_usec * 1000; + } + return syscall_cp(SYS_pselect6, n, rfds, wfds, efds, tv ? &ts : 0, data); +#endif } diff --git a/src/stat/chmod.c b/src/stat/chmod.c index beb66e5..d4f53c5 100644 --- a/src/stat/chmod.c +++ b/src/stat/chmod.c @@ -1,7 +1,12 @@ #include +#include #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/futimesat.c b/src/stat/futimesat.c index dbefc84..5990aa6 100644 --- a/src/stat/futimesat.c +++ b/src/stat/futimesat.c @@ -1,10 +1,23 @@ #define _GNU_SOURCE #include +#include +#include #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 >= 1000000U) + 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 8f60358..5e8b84f 100644 --- a/src/stat/lstat.c +++ b/src/stat/lstat.c @@ -1,10 +1,15 @@ #include +#include #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 770e1cc..32625b7 100644 --- a/src/stat/mkdir.c +++ b/src/stat/mkdir.c @@ -1,7 +1,12 @@ #include +#include #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 c319657..beebd84 100644 --- a/src/stat/mknod.c +++ b/src/stat/mknod.c @@ -1,7 +1,12 @@ #include +#include #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 c6de716..b4433a0 100644 --- a/src/stat/stat.c +++ b/src/stat/stat.c @@ -1,10 +1,15 @@ #include +#include #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 929698b..abc8d74 100644 --- a/src/stat/utimensat.c +++ b/src/stat/utimensat.c @@ -1,7 +1,40 @@ #include +#include +#include +#include #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); + if (r != -ENOSYS || flags) return __syscall_ret(r); + +#ifdef SYS_futimesat + struct timeval *tv = 0; + if (times) { + struct timeval tmp[2]; + int i; + tv = tmp; + for (i=0; i<2; i++) { + if (times[i].tv_nsec >= 1000000000U) { + 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); } diff --git a/src/stdio/rename.c b/src/stdio/rename.c index 97f1453..04c90c0 100644 --- a/src/stdio/rename.c +++ b/src/stdio/rename.c @@ -1,7 +1,12 @@ #include +#include #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 } diff --git a/src/time/utime.c b/src/time/utime.c index b2b5741..3b5f4e3 100644 --- a/src/time/utime.c +++ b/src/time/utime.c @@ -1,14 +1,16 @@ #include -#include -#include "syscall.h" +#include +#include +#include int utime(const char *path, const struct utimbuf *times) { + struct timespec *ts = 0; if (times) { - struct timeval tv[2] = { + struct timespec tmp[2] = { { .tv_sec = times->actime }, { .tv_sec = times->modtime } }; - return syscall(SYS_utimes, path, tv); + ts = tmp; } - return syscall(SYS_utimes, path, 0); + return utimensat(AT_FDCWD, path, ts, 0); } diff --git a/src/unistd/access.c b/src/unistd/access.c index e7ce73a..d6eed68 100644 --- a/src/unistd/access.c +++ b/src/unistd/access.c @@ -1,7 +1,12 @@ #include +#include #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 } diff --git a/src/unistd/chown.c b/src/unistd/chown.c index 95f6f61..14b0325 100644 --- a/src/unistd/chown.c +++ b/src/unistd/chown.c @@ -1,7 +1,12 @@ #include +#include #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 } diff --git a/src/unistd/dup2.c b/src/unistd/dup2.c index 87a0d44..ed04a89 100644 --- a/src/unistd/dup2.c +++ b/src/unistd/dup2.c @@ -5,6 +5,11 @@ int dup2(int old, int new) { int r; +#ifdef SYS_dup2 while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); +#else + while ((r=__syscall(SYS_dup3, old, new, 0))==-EBUSY); + if (r==-EINVAL && old==new) return new; +#endif return __syscall_ret(r); } diff --git a/src/unistd/getpgrp.c b/src/unistd/getpgrp.c index 433f42e..5a74d4f 100644 --- a/src/unistd/getpgrp.c +++ b/src/unistd/getpgrp.c @@ -3,5 +3,9 @@ pid_t getpgrp(void) { +#ifdef SYS_getpgrp return __syscall(SYS_getpgrp); +#else + return __syscall(SYS_getpgid, 0); +#endif } diff --git a/src/unistd/lchown.c b/src/unistd/lchown.c index de871ae..ccd5ee0 100644 --- a/src/unistd/lchown.c +++ b/src/unistd/lchown.c @@ -1,7 +1,12 @@ #include +#include #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 } diff --git a/src/unistd/link.c b/src/unistd/link.c index 20193f2..feec18e 100644 --- a/src/unistd/link.c +++ b/src/unistd/link.c @@ -1,7 +1,12 @@ #include +#include #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 } diff --git a/src/unistd/pause.c b/src/unistd/pause.c index f7ed17d..50bf3b1 100644 --- a/src/unistd/pause.c +++ b/src/unistd/pause.c @@ -4,5 +4,11 @@ int pause(void) { +#ifdef SYS_pause return syscall_cp(SYS_pause); +#else + sigset_t mask; + __syscall(SYS_rt_sigprocmask, SIG_BLOCK, 0, &mask, _NSIG/8); + return syscall_cp(SYS_rt_sigsuspend, &mask, _NSIG/8); +#endif } diff --git a/src/unistd/pipe.c b/src/unistd/pipe.c index 36c6f13..d07b8d2 100644 --- a/src/unistd/pipe.c +++ b/src/unistd/pipe.c @@ -3,5 +3,9 @@ int pipe(int fd[2]) { +#ifdef SYS_pipe return syscall(SYS_pipe, fd); +#else + return syscall(SYS_pipe2, fd, 0); +#endif } diff --git a/src/unistd/readlink.c b/src/unistd/readlink.c index ec291e3..a152d52 100644 --- a/src/unistd/readlink.c +++ b/src/unistd/readlink.c @@ -1,7 +1,12 @@ #include +#include #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 } diff --git a/src/unistd/rmdir.c b/src/unistd/rmdir.c index dfe1605..6825ffc 100644 --- a/src/unistd/rmdir.c +++ b/src/unistd/rmdir.c @@ -1,7 +1,12 @@ #include +#include #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 } diff --git a/src/unistd/symlink.c b/src/unistd/symlink.c index 5902d45..0973d78 100644 --- a/src/unistd/symlink.c +++ b/src/unistd/symlink.c @@ -1,7 +1,12 @@ #include +#include #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 } diff --git a/src/unistd/unlink.c b/src/unistd/unlink.c index bdb37be..c40c28d 100644 --- a/src/unistd/unlink.c +++ b/src/unistd/unlink.c @@ -1,7 +1,12 @@ #include +#include #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 }