int __clock_gettime(clockid_t clk, struct timespec *ts) { int r; #ifdef VDSO_CGT_SYM int (*f)(clockid_t, struct timespec *) = (int (*)(clockid_t, struct timespec *))vdso_func; if (f) { r = f(clk, ts); if (!r) return r; if (r == -EINVAL) return __syscall_ret(r); /* Fall through on errors other than EINVAL. Some buggy * vdso implementations return ENOSYS for clocks they * can't handle, rather than making the syscall. This * also handles the case where cgt_init fails to find * a vdso function to use. */ } #endif r = __syscall(SYS_clock_gettime, clk, ts); if (r == -ENOSYS) { if (clk == CLOCK_REALTIME) { __syscall(SYS_gettimeofday, ts, 0); ts->tv_nsec = (int)ts->tv_nsec * 1000; return 0; } r = -EINVAL; } return __syscall_ret(r); }
int futimens(int fd, const struct timespec times[2]) { int r = __syscall(SYS_utimensat, fd, 0, times, 0); #ifdef SYS_futimesat if (r != -ENOSYS) 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, 0, tv); if (r != -ENOSYS || fd != AT_FDCWD) return __syscall_ret(r); r = __syscall(SYS_utimes, 0, tv); #endif return __syscall_ret(r); }
int signalfd(int fd, const sigset_t *sigs, int flags) { int ret = __syscall(SYS_signalfd4, fd, sigs, _NSIG/8, flags); if (ret != -ENOSYS) return __syscall_ret(ret); ret = __syscall(SYS_signalfd, fd, sigs, _NSIG/8); if (ret >= 0) { if (flags & SFD_CLOEXEC) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); if (flags & SFD_NONBLOCK) __syscall(SYS_fcntl, ret, F_SETFL, O_NONBLOCK); } return __syscall_ret(ret); }
int epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to, const sigset_t *sigs) { 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_create1(int 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 fchdir(int fd) { int ret = __syscall(SYS_fchdir, fd); if (ret != -EBADF || fd < 0) return __syscall_ret(ret); char buf[15+3*sizeof(int)]; __procfdname(buf, fd); return syscall(SYS_chdir, buf); }
int fstat(int fd, struct stat *st) { int ret = __syscall(SYS_fstat, fd, mcfi_sandbox_mask(st)); if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0) return __syscall_ret(ret); char buf[15+3*sizeof(int)]; __procfdname(buf, fd); return syscall(SYS_stat, buf, mcfi_sandbox_mask(st)); }
int fexecve(int fd, char *const argv[], char *const envp[]) { int r = __syscall(SYS_execveat, fd, "", argv, envp, AT_EMPTY_PATH); if (r != -ENOSYS) return __syscall_ret(r); char buf[15 + 3*sizeof(int)]; __procfdname(buf, fd); execve(buf, argv, envp); if (errno == ENOENT) errno = EBADF; return -1; }
int fcntl64(int fd, int cmd, ...) { unsigned long arg; va_list ap; va_start(ap, cmd); arg = va_arg(ap, unsigned long); va_end(ap); if (cmd == F_SETFL) arg |= O_LARGEFILE; if (cmd == F_SETLKW) return syscall(SYS_fcntl, fd, cmd, (void *)arg); if (cmd == F_GETOWN) { struct f_owner_ex ex; int ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex); if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd, (void *)arg); if (ret) return __syscall_ret(ret); return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid; } if (cmd == F_DUPFD_CLOEXEC) { int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg); if (ret != -EINVAL) { if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); return __syscall_ret(ret); } ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0); if (ret != -EINVAL) { if (ret >= 0) __syscall(SYS_close, ret); return __syscall_ret(-EINVAL); } ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg); if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); return __syscall_ret(ret); } switch (cmd) { case F_SETLK: case F_GETLK: case F_GETOWN_EX: case F_SETOWN_EX: return syscall(SYS_fcntl, fd, cmd, (void *)arg); default: return syscall(SYS_fcntl, fd, cmd, arg); } }
int fchmodat(int fd, const char *path, mode_t mode, int flag) { if (!flag) return syscall(SYS_fchmodat, fd, path, mode, flag); if (flag != AT_SYMLINK_NOFOLLOW) return __syscall_ret(-EINVAL); struct stat st; int ret, fd2; char proc[15+3*sizeof(int)]; if ((ret = __syscall(SYS_fstatat, fd, path, &st, flag))) return __syscall_ret(ret); if (S_ISLNK(st.st_mode)) return __syscall_ret(-EOPNOTSUPP); if ((fd2 = __syscall(SYS_openat, fd, path, O_RDONLY|O_PATH|O_NOFOLLOW|O_NOCTTY)) < 0) { if (fd2 == -ELOOP) return __syscall_ret(-EOPNOTSUPP); return __syscall_ret(fd2); } __procfdname(proc, fd2); if (!(ret = __syscall(SYS_stat, proc, &st)) && !S_ISLNK(st.st_mode)) ret = __syscall(SYS_chmod, proc, mode); __syscall(SYS_close, fd2); return __syscall_ret(ret); }
long syscall(long n, ...) { va_list ap; syscall_arg_t a, b, c, d, e, f; va_start(ap, n); a = va_arg(ap, syscall_arg_t); b = va_arg(ap, syscall_arg_t); c = va_arg(ap, syscall_arg_t); d = va_arg(ap, syscall_arg_t); e = va_arg(ap, syscall_arg_t); f = va_arg(ap, syscall_arg_t); va_end(ap); return __syscall_ret(__syscall(n, a, b, c, d, e, f)); }
int fstat(int fd, struct stat* st) { int ret = __syscall(SYS_fstat, fd, st); if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0) return __syscall_ret(ret); char buf[15 + 3 * sizeof(int)]; __procfdname(buf, fd); #ifdef SYS_stat return syscall(SYS_stat, buf, st); #else return syscall(SYS_fstatat, AT_FDCWD, buf, st, 0); #endif }
int pipe2(int fd[2], int flag) { if (!flag) return pipe(fd); int ret = __syscall(SYS_pipe2,mcfi_sandbox_mask(fd), flag); if (ret != -ENOSYS) return __syscall_ret(ret); ret = pipe(fd); if (ret) return ret; if (flag & O_CLOEXEC) { __syscall(SYS_fcntl, fd[0], F_SETFD, FD_CLOEXEC); __syscall(SYS_fcntl, fd[1], F_SETFD, FD_CLOEXEC); } if (flag & O_NONBLOCK) { __syscall(SYS_fcntl, fd[0], F_SETFL, O_NONBLOCK); __syscall(SYS_fcntl, fd[1], F_SETFL, O_NONBLOCK); } return 0; }
void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off) { long ret; if (off & OFF_MASK) { errno = EINVAL; return MAP_FAILED; } if (len >= PTRDIFF_MAX) { errno = ENOMEM; return MAP_FAILED; } if (flags & MAP_FIXED) { __vm_wait(); } #ifdef SYS_mmap2 ret = __syscall(SYS_mmap2, start, len, prot, flags, fd, off/UNIT); #else ret = __syscall(SYS_mmap, start, len, prot, flags, fd, off); #endif /* Fixup incorrect EPERM from kernel. */ if (ret == -EPERM && !start && (flags&MAP_ANON) && !(flags&MAP_FIXED)) ret = -ENOMEM; return (void *)__syscall_ret(ret); }
void *sbrk(intptr_t inc) { if (inc) return (void *)__syscall_ret(-ENOMEM); return (void *)__syscall(SYS_brk, 0); }
int sched_getparam(pid_t pid, struct sched_param *param) { return __syscall_ret(-ENOSYS); }
int sched_setscheduler(pid_t pid, int sched, const struct sched_param *param) { return __syscall_ret(-ENOSYS); }