about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/env/__libc_start_main.c5
-rw-r--r--src/linux/epoll.c16
-rw-r--r--src/linux/eventfd.c6
-rw-r--r--src/linux/inotify.c8
-rw-r--r--src/linux/signalfd.c2
-rw-r--r--src/linux/utimes.c5
-rw-r--r--src/process/fork.c5
-rw-r--r--src/process/posix_spawn.c18
-rw-r--r--src/select/poll.c8
-rw-r--r--src/select/select.c18
-rw-r--r--src/stat/chmod.c5
-rw-r--r--src/stat/fchmod.c4
-rw-r--r--src/stat/fchmodat.c5
-rw-r--r--src/stat/futimesat.c21
-rw-r--r--src/stat/lstat.c5
-rw-r--r--src/stat/mkdir.c5
-rw-r--r--src/stat/mknod.c5
-rw-r--r--src/stat/stat.c5
-rw-r--r--src/stat/utimensat.c32
-rw-r--r--src/stdio/remove.c14
-rw-r--r--src/stdio/rename.c5
-rw-r--r--src/stdio/tempnam.c5
-rw-r--r--src/stdio/tmpfile.c4
-rw-r--r--src/stdio/tmpnam.c5
-rw-r--r--src/time/utime.c15
-rw-r--r--src/unistd/access.c5
-rw-r--r--src/unistd/chown.c5
-rw-r--r--src/unistd/dup2.c10
-rw-r--r--src/unistd/dup3.c4
-rw-r--r--src/unistd/fchown.c5
-rw-r--r--src/unistd/getpgrp.c2
-rw-r--r--src/unistd/lchown.c5
-rw-r--r--src/unistd/link.c5
-rw-r--r--src/unistd/pause.c5
-rw-r--r--src/unistd/pipe.c4
-rw-r--r--src/unistd/readlink.c5
-rw-r--r--src/unistd/rmdir.c5
-rw-r--r--src/unistd/symlink.c5
-rw-r--r--src/unistd/unlink.c5
39 files changed, 267 insertions, 29 deletions
diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c
index d7481c25..c10a3f35 100644
--- a/src/env/__libc_start_main.c
+++ b/src/env/__libc_start_main.c
@@ -1,6 +1,7 @@
 #include <elf.h>
 #include <poll.h>
 #include <fcntl.h>
+#include <signal.h>
 #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/epoll.c b/src/linux/epoll.c
index 030786d3..b45344fb 100644
--- a/src/linux/epoll.c
+++ b/src/linux/epoll.c
@@ -4,12 +4,16 @@
 
 int epoll_create(int size)
 {
-	return syscall(SYS_epoll_create, size);
+	return epoll_create1(0);
 }
 
 int epoll_create1(int flags)
 {
-	return syscall(SYS_epoll_create1, flags);
+	int r = __syscall(SYS_epoll_create1, flags);
+#ifdef SYS_epoll_create
+	if (r==-ENOSYS && !flags) r = __syscall(SYS_epoll_create, 1);
+#endif
+	return __syscall_ret(r);
 }
 
 int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev)
@@ -19,10 +23,14 @@ int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev)
 
 int epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to, const sigset_t *sigs)
 {
-	return syscall(SYS_epoll_pwait, fd, ev, cnt, to, sigs, _NSIG/8);
+	int r = __syscall(SYS_epoll_pwait, fd, ev, cnt, to, sigs, _NSIG/8);
+#ifdef SYS_epoll_wait
+	if (r==-ENOSYS && !sigs) r = __syscall(SYS_epoll_wait, fd, ev, cnt, to);
+#endif
+	return __syscall_ret(r);
 }
 
 int epoll_wait(int fd, struct epoll_event *ev, int cnt, int to)
 {
-	return syscall(SYS_epoll_wait, fd, ev, cnt, to);
+	return epoll_pwait(fd, ev, cnt, to, 0);
 }
diff --git a/src/linux/eventfd.c b/src/linux/eventfd.c
index 53066487..39968034 100644
--- a/src/linux/eventfd.c
+++ b/src/linux/eventfd.c
@@ -4,7 +4,11 @@
 
 int eventfd(unsigned int count, int flags)
 {
-	return syscall(flags ? SYS_eventfd2 : SYS_eventfd, count, flags);
+	int r = __syscall(SYS_eventfd2, count, flags);
+#ifdef SYS_eventfd
+	if (r==-ENOSYS && !flags) r = __syscall(SYS_eventfd, count);
+#endif
+	return __syscall_ret(r);
 }
 
 int eventfd_read(int fd, eventfd_t *value)
diff --git a/src/linux/inotify.c b/src/linux/inotify.c
index a417c891..84a56154 100644
--- a/src/linux/inotify.c
+++ b/src/linux/inotify.c
@@ -3,11 +3,15 @@
 
 int inotify_init()
 {
-	return syscall(SYS_inotify_init);
+	return inotify_init1(0);
 }
 int inotify_init1(int flags)
 {
-	return syscall(SYS_inotify_init1, flags);
+	int r = __syscall(SYS_inotify_init1, flags);
+#ifdef SYS_inotify_init
+	if (r==-ENOSYS && !flags) r = __syscall(SYS_inotify_init);
+#endif
+	return __syscall_ret(r);
 }
 
 int inotify_add_watch(int fd, const char *pathname, uint32_t mask)
diff --git a/src/linux/signalfd.c b/src/linux/signalfd.c
index da6bcedb..4bf43326 100644
--- a/src/linux/signalfd.c
+++ b/src/linux/signalfd.c
@@ -7,6 +7,7 @@
 int signalfd(int fd, const sigset_t *sigs, int flags)
 {
 	int ret = __syscall(SYS_signalfd4, fd, sigs, _NSIG/8, flags);
+#ifdef SYS_signalfd
 	if (ret != -ENOSYS) return __syscall_ret(ret);
 	ret = __syscall(SYS_signalfd, fd, sigs, _NSIG/8);
 	if (ret >= 0) {
@@ -15,5 +16,6 @@ int signalfd(int fd, const sigset_t *sigs, int flags)
 		if (flags & SFD_NONBLOCK)
 			__syscall(SYS_fcntl, ret, F_SETFL, O_NONBLOCK);
 	}
+#endif
 	return __syscall_ret(ret);
 }
diff --git a/src/linux/utimes.c b/src/linux/utimes.c
index 70c0695f..b814c88b 100644
--- a/src/linux/utimes.c
+++ b/src/linux/utimes.c
@@ -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);
 }
diff --git a/src/process/fork.c b/src/process/fork.c
index 864c7d7a..f8cf21e7 100644
--- a/src/process/fork.c
+++ b/src/process/fork.c
@@ -1,5 +1,6 @@
 #include <unistd.h>
 #include <string.h>
+#include <signal.h>
 #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, 0);
+#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 08644f51..08928b0e 100644
--- a/src/process/posix_spawn.c
+++ b/src/process/posix_spawn.c
@@ -22,6 +22,20 @@ struct args {
 
 void __get_handler_set(sigset_t *);
 
+static int __sys_dup2(int old, int new)
+{
+#ifdef SYS_dup2
+	return __syscall(SYS_dup2, old, new);
+#else
+	if (old==new) {
+		int r = __syscall(SYS_fcntl, old, F_GETFD);
+		return r<0 ? r : old;
+	} else {
+		return __syscall(SYS_dup3, old, new, 0);
+	}
+#endif
+}
+
 static int child(void *args_vp)
 {
 	int i, ret;
@@ -92,14 +106,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=__sys_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=__sys_dup2(fd, op->fd))<0)
 						goto fail;
 					__syscall(SYS_close, fd);
 				}
diff --git a/src/select/poll.c b/src/select/poll.c
index f1e73e82..9e0bcbd8 100644
--- a/src/select/poll.c
+++ b/src/select/poll.c
@@ -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
 }
diff --git a/src/select/select.c b/src/select/select.c
index f93597b5..7b5f6dcf 100644
--- a/src/select/select.c
+++ b/src/select/select.c
@@ -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
 }
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);
 }
diff --git a/src/stdio/remove.c b/src/stdio/remove.c
index e147ba25..942e301a 100644
--- a/src/stdio/remove.c
+++ b/src/stdio/remove.c
@@ -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);
 }
diff --git a/src/stdio/rename.c b/src/stdio/rename.c
index 97f14535..04c90c01 100644
--- a/src/stdio/rename.c
+++ b/src/stdio/rename.c
@@ -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
 }
diff --git a/src/stdio/tempnam.c b/src/stdio/tempnam.c
index 9bf8c727..45a5f266 100644
--- a/src/stdio/tempnam.c
+++ b/src/stdio/tempnam.c
@@ -36,7 +36,12 @@ char *tempnam(const char *dir, const char *pfx)
 
 	for (try=0; try<MAXTRIES; try++) {
 		__randname(s+l-6);
+#ifdef SYS_lstat
 		r = __syscall(SYS_lstat, s, &(struct stat){0});
+#else
+		r = __syscall(SYS_fstatat, AT_FDCWD, s,
+			&(struct stat){0}, AT_SYMLINK_NOFOLLOW);
+#endif
 		if (r == -ENOENT) return strdup(s);
 	}
 	return 0;
diff --git a/src/stdio/tmpfile.c b/src/stdio/tmpfile.c
index c8569948..a7d0000a 100644
--- a/src/stdio/tmpfile.c
+++ b/src/stdio/tmpfile.c
@@ -17,7 +17,11 @@ FILE *tmpfile(void)
 		fd = sys_open(s, O_RDWR|O_CREAT|O_EXCL, 0600);
 		if (fd >= 0) {
 			f = __fdopen(fd, "w+");
+#ifdef SYS_unlink
 			__syscall(SYS_unlink, s);
+#else
+			__syscall(SYS_unlinkat, AT_FDCWD, s, 0);
+#endif
 			return f;
 		}
 	}
diff --git a/src/stdio/tmpnam.c b/src/stdio/tmpnam.c
index c3f5a2ff..449eb9b0 100644
--- a/src/stdio/tmpnam.c
+++ b/src/stdio/tmpnam.c
@@ -17,7 +17,12 @@ char *tmpnam(char *buf)
 	int r;
 	for (try=0; try<MAXTRIES; try++) {
 		__randname(s+12);
+#ifdef SYS_lstat
 		r = __syscall(SYS_lstat, s, &(struct stat){0});
+#else
+		r = __syscall(SYS_fstatat, AT_FDCWD, s,
+			&(struct stat){0}, AT_SYMLINK_NOFOLLOW);
+#endif
 		if (r == -ENOENT) return strcpy(buf ? buf : internal, s);
 	}
 	return 0;
diff --git a/src/time/utime.c b/src/time/utime.c
index b2b5741b..e7592b29 100644
--- a/src/time/utime.c
+++ b/src/time/utime.c
@@ -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);
 }
diff --git a/src/unistd/access.c b/src/unistd/access.c
index e7ce73a2..d6eed683 100644
--- a/src/unistd/access.c
+++ b/src/unistd/access.c
@@ -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
 }
diff --git a/src/unistd/chown.c b/src/unistd/chown.c
index 95f6f61e..14b03255 100644
--- a/src/unistd/chown.c
+++ b/src/unistd/chown.c
@@ -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
 }
diff --git a/src/unistd/dup2.c b/src/unistd/dup2.c
index 87a0d445..8f43c6dd 100644
--- a/src/unistd/dup2.c
+++ b/src/unistd/dup2.c
@@ -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);
 }
diff --git a/src/unistd/dup3.c b/src/unistd/dup3.c
index 1f7134b3..0eb6caf5 100644
--- a/src/unistd/dup3.c
+++ b/src/unistd/dup3.c
@@ -8,6 +8,7 @@
 int __dup3(int old, int new, int flags)
 {
 	int r;
+#ifdef SYS_dup2
 	if (old==new) return __syscall_ret(-EINVAL);
 	if (flags & O_CLOEXEC) {
 		while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
@@ -15,6 +16,9 @@ int __dup3(int old, int new, int flags)
 	}
 	while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
 	if (flags & O_CLOEXEC) __syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC);
+#else
+	while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
+#endif
 	return __syscall_ret(r);
 }
 
diff --git a/src/unistd/fchown.c b/src/unistd/fchown.c
index 36633b0e..03459849 100644
--- a/src/unistd/fchown.c
+++ b/src/unistd/fchown.c
@@ -13,5 +13,10 @@ int fchown(int fd, uid_t uid, gid_t gid)
 
 	char buf[15+3*sizeof(int)];
 	__procfdname(buf, fd);
+#ifdef SYS_chown
 	return syscall(SYS_chown, buf, uid, gid);
+#else
+	return syscall(SYS_fchownat, AT_FDCWD, buf, uid, gid);
+#endif
+
 }
diff --git a/src/unistd/getpgrp.c b/src/unistd/getpgrp.c
index 433f42e8..90e9bb07 100644
--- a/src/unistd/getpgrp.c
+++ b/src/unistd/getpgrp.c
@@ -3,5 +3,5 @@
 
 pid_t getpgrp(void)
 {
-	return __syscall(SYS_getpgrp);
+	return __syscall(SYS_getpgid, 0);
 }
diff --git a/src/unistd/lchown.c b/src/unistd/lchown.c
index de871aeb..ccd5ee02 100644
--- a/src/unistd/lchown.c
+++ b/src/unistd/lchown.c
@@ -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
 }
diff --git a/src/unistd/link.c b/src/unistd/link.c
index 20193f2a..feec18e5 100644
--- a/src/unistd/link.c
+++ b/src/unistd/link.c
@@ -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
 }
diff --git a/src/unistd/pause.c b/src/unistd/pause.c
index f7ed17d1..56eb171e 100644
--- a/src/unistd/pause.c
+++ b/src/unistd/pause.c
@@ -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
 }
diff --git a/src/unistd/pipe.c b/src/unistd/pipe.c
index 36c6f13e..d07b8d24 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 ec291e3d..a152d524 100644
--- a/src/unistd/readlink.c
+++ b/src/unistd/readlink.c
@@ -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
 }
diff --git a/src/unistd/rmdir.c b/src/unistd/rmdir.c
index dfe1605d..6825ffc8 100644
--- a/src/unistd/rmdir.c
+++ b/src/unistd/rmdir.c
@@ -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
 }
diff --git a/src/unistd/symlink.c b/src/unistd/symlink.c
index 5902d45a..0973d78a 100644
--- a/src/unistd/symlink.c
+++ b/src/unistd/symlink.c
@@ -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
 }
diff --git a/src/unistd/unlink.c b/src/unistd/unlink.c
index bdb37bea..c40c28d5 100644
--- a/src/unistd/unlink.c
+++ b/src/unistd/unlink.c
@@ -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
 }