int signalfd (int fd, const sigset_t *mask, int flags) { #ifdef __NR_signalfd4 int res = INLINE_SYSCALL (signalfd4, 4, fd, mask, _NSIG / 8, flags); # ifndef __ASSUME_SIGNALFD4 if (res != -1 || errno != ENOSYS) # endif return res; #endif #ifndef __ASSUME_SIGNALFD4 /* The old system call has no flag parameter which is bad. So we have to wait until we have to support to pass additional values to the kernel (sys_indirect) before implementing setting flags like O_NONBLOCK etc. */ if (flags != 0) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); # ifdef __NR_signalfd return INLINE_SYSCALL (signalfd, 3, fd, mask, _NSIG / 8); # else return INLINE_SYSCALL_ERROR_RETURN_VALUE (ENOSYS); # endif #elif !defined __NR_signalfd4 # error "__ASSUME_SIGNALFD4 defined but not __NR_signalfd4" #endif }
int eventfd (unsigned int count, int flags) { #ifdef __NR_eventfd2 int res = INLINE_SYSCALL (eventfd2, 2, count, flags); # ifndef __ASSUME_EVENTFD2 if (res != -1 || errno != ENOSYS) # endif return res; #endif #ifndef __ASSUME_EVENTFD2 /* The old system call has no flag parameter which is bad. So we have to wait until we have to support to pass additional values to the kernel (sys_indirect) before implementing setting flags like O_NONBLOCK etc. */ if (flags != 0) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); # ifdef __NR_eventfd return INLINE_SYSCALL (eventfd, 1, count); # else return INLINE_SYSCALL_ERROR_RETURN_VALUE (ENOSYS); # endif #elif !defined __NR_eventfd2 # error "__ASSUME_EVENTFD2 defined but not __NR_eventfd2" #endif }
int prlimit (__pid_t pid, enum __rlimit_resource resource, const struct rlimit *new_rlimit, struct rlimit *old_rlimit) { struct rlimit64 new_rlimit64_mem; struct rlimit64 *new_rlimit64 = NULL; struct rlimit64 old_rlimit64_mem; struct rlimit64 *old_rlimit64 = (old_rlimit != NULL ? &old_rlimit64_mem : NULL); if (new_rlimit != NULL) { if (new_rlimit->rlim_cur == RLIM_INFINITY) new_rlimit64_mem.rlim_cur = RLIM64_INFINITY; else new_rlimit64_mem.rlim_cur = new_rlimit->rlim_cur; if (new_rlimit->rlim_max == RLIM_INFINITY) new_rlimit64_mem.rlim_max = RLIM64_INFINITY; else new_rlimit64_mem.rlim_max = new_rlimit->rlim_max; new_rlimit64 = &new_rlimit64_mem; } int res = INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit64, old_rlimit64); if (res == 0 && old_rlimit != NULL) { /* The prlimit64 syscall is ill-designed for 32-bit machines. We have to provide a 32-bit variant since otherwise the LFS system would not work. The infinity value can be translated, but otherwise what shall we do if the syscall succeeds but the old values do not fit into a rlimit structure? We cannot return an error because the operation itself worked. Best is perhaps to return RLIM_INFINITY. */ old_rlimit->rlim_cur = old_rlimit64_mem.rlim_cur; if (old_rlimit->rlim_cur != old_rlimit64_mem.rlim_cur) { if ((new_rlimit == NULL) && (old_rlimit64_mem.rlim_cur != RLIM64_INFINITY)) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW); old_rlimit->rlim_cur = RLIM_INFINITY; } old_rlimit->rlim_max = old_rlimit64_mem.rlim_max; if (old_rlimit->rlim_max != old_rlimit64_mem.rlim_max) { if ((new_rlimit == NULL) && (old_rlimit64_mem.rlim_max != RLIM64_INFINITY)) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW); old_rlimit->rlim_max = RLIM_INFINITY; } } return res; }
int __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag) { if (__glibc_unlikely (vers != _STAT_VER_LINUX)) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); int result; INTERNAL_SYSCALL_DECL (err); result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, st, flag); if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1)) return 0; else return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result, err)); }
__ptr_t __mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset) { if (offset & (MMAP_PAGE_UNIT - 1)) return (__ptr_t) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); return (__ptr_t) INLINE_SYSCALL (mmap2, 6, addr, len, prot, flags, fd, offset / MMAP_PAGE_UNIT); }
/* Change the access time of the file associated with FD to TSP[0] and the modification time of FILE to TSP[1]. Starting with 2.6.22 the Linux kernel has the utimensat syscall which can be used to implement futimens. */ int futimens (int fd, const struct timespec tsp[2]) { if (fd < 0) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF); /* Avoid implicit array coercion in syscall macros. */ return INLINE_SYSCALL (utimensat, 4, fd, NULL, &tsp[0], 0); }
int lockf64 (int fd, int cmd, off64_t len64) { struct flock64 fl64; int cmd64; int result; memset ((char *) &fl64, '\0', sizeof (fl64)); fl64.l_whence = SEEK_CUR; fl64.l_start = 0; fl64.l_len = len64; switch (cmd) { case F_TEST: /* Test the lock: return 0 if FD is unlocked or locked by this process; return -1, set errno to EACCES, if another process holds the lock. */ fl64.l_type = F_RDLCK; INTERNAL_SYSCALL_DECL (err); result = INTERNAL_SYSCALL (fcntl64, err, 3, fd, F_GETLK64, &fl64); if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err))) return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result, err)); if (fl64.l_type == F_UNLCK || fl64.l_pid == __getpid ()) return 0; return INLINE_SYSCALL_ERROR_RETURN_VALUE (EACCES); case F_ULOCK: fl64.l_type = F_UNLCK; cmd64 = F_SETLK64; break; case F_LOCK: fl64.l_type = F_WRLCK; cmd64 = F_SETLKW64; break; case F_TLOCK: fl64.l_type = F_WRLCK; cmd64 = F_SETLK64; break; default: return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); } return INLINE_SYSCALL (fcntl64, 3, fd, cmd64, &fl64); }
int faccessat (int fd, const char *file, int mode, int flag) { if (flag & ~(AT_SYMLINK_NOFOLLOW | AT_EACCESS)) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); if ((flag == 0 || ((flag & ~AT_EACCESS) == 0 && ! __libc_enable_secure))) return INLINE_SYSCALL (faccessat, 3, fd, file, mode); struct stat64 stats; if (__fxstatat64 (_STAT_VER, fd, file, &stats, flag & AT_SYMLINK_NOFOLLOW)) return -1; mode &= (X_OK | W_OK | R_OK); /* Clear any bogus bits. */ #if R_OK != S_IROTH || W_OK != S_IWOTH || X_OK != S_IXOTH # error Oops, portability assumptions incorrect. #endif if (mode == F_OK) return 0; /* The file exists. */ uid_t uid = (flag & AT_EACCESS) ? __geteuid () : __getuid (); /* The super-user can read and write any file, and execute any file that anyone can execute. */ if (uid == 0 && ((mode & X_OK) == 0 || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))) return 0; int granted = (uid == stats.st_uid ? (unsigned int) (stats.st_mode & (mode << 6)) >> 6 : (stats.st_gid == ((flag & AT_EACCESS) ? __getegid () : __getgid ()) || __group_member (stats.st_gid)) ? (unsigned int) (stats.st_mode & (mode << 3)) >> 3 : (stats.st_mode & mode)); if (granted == mode) return 0; return INLINE_SYSCALL_ERROR_RETURN_VALUE (EACCES); }
int ustat (dev_t dev, struct ustat *ubuf) { unsigned long long int k_dev; /* We must convert the value to dev_t type used by the kernel. */ k_dev = dev & ((1ULL << 32) - 1); if (k_dev != dev) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); return INLINE_SYSCALL (ustat, 2, (unsigned int) k_dev, ubuf); }
int seteuid (uid_t uid) { int result; if (uid == (uid_t) ~0) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); result = INLINE_SETXID_SYSCALL (setresuid32, 3, -1, uid, -1); return result; }
/* Get information about the file NAME relative to FD in ST. */ int __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag) { int result; INTERNAL_SYSCALL_DECL (err); struct stat64 st64; result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, &st64, flag); if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err))) return INLINE_SYSCALL_ERROR_RETURN_VALUE (-result); else return __xstat32_conv (vers, &st64, st); }
static int do_fcntl (int fd, int cmd, void *arg) { if (cmd != F_GETOWN) return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg); INTERNAL_SYSCALL_DECL (err); struct f_owner_ex fex; int res = INTERNAL_SYSCALL (fcntl, err, 3, fd, F_GETOWN_EX, &fex); if (!INTERNAL_SYSCALL_ERROR_P (res, err)) return fex.type == F_OWNER_GID ? -fex.pid : fex.pid; return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (res, err)); }
int setegid (gid_t gid) { int result; if (gid == (gid_t) ~0) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); #ifdef __NR_setresgid32 result = INLINE_SETXID_SYSCALL (setresgid32, 3, -1, gid, -1); #else result = INLINE_SETXID_SYSCALL (setresgid, 3, -1, gid, -1); #endif return result; }
/* Change the access time of the file associated with FD to TVP[0] and the modification time of FILE to TVP[1]. Starting with 2.6.22 the Linux kernel has the utimensat syscall which can be used to implement futimes. */ int __futimes (int fd, const struct timeval tvp[2]) { /* The utimensat system call expects timespec not timeval. */ struct timespec ts[2]; if (tvp != NULL) { if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); TIMEVAL_TO_TIMESPEC (&tvp[0], &ts[0]); TIMEVAL_TO_TIMESPEC (&tvp[1], &ts[1]); } return INLINE_SYSCALL (utimensat, 4, fd, NULL, tvp ? &ts : NULL, 0); }
void * shmat (int shmid, const void *shmaddr, int shmflg) { INTERNAL_SYSCALL_DECL(err); unsigned long resultvar; void *raddr; resultvar = INTERNAL_SYSCALL (ipc, err, 5, IPCOP_shmat, shmid, shmflg, (long int) &raddr, (void *) shmaddr); if (INTERNAL_SYSCALL_ERROR_P (resultvar, err)) return (void *) INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (resultvar, err)); return raddr; }
int lutimes (const char *file, const struct timeval tvp[2]) { /* The system call espects timespec, not timeval. */ struct timespec ts[2]; if (tvp != NULL) { if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); TIMEVAL_TO_TIMESPEC (&tvp[0], &ts[0]); TIMEVAL_TO_TIMESPEC (&tvp[1], &ts[1]); } return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, tvp ? ts : NULL, AT_SYMLINK_NOFOLLOW); }
/* Get information about the file NAME in BUF. */ int __xstat (int vers, const char *name, struct stat *buf) { if (vers == _STAT_VER_KERNEL) return INLINE_SYSCALL (stat, 2, name, buf); #ifdef STAT_IS_KERNEL_STAT return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); #else struct kernel_stat kbuf; int result; result = INLINE_SYSCALL (stat, 2, name, &kbuf); if (result == 0) result = __xstat_conv (vers, &kbuf, buf); return result; #endif }
/* Get information about the file NAME in BUF. */ int __lxstat (int vers, const char *name, struct stat *buf) { int result; if (vers == _STAT_VER_KERNEL) return INLINE_SYSCALL (lstat, 2, name, (struct kernel_stat *) buf); { struct stat64 buf64; INTERNAL_SYSCALL_DECL (err); result = INTERNAL_SYSCALL (lstat64, err, 2, name, &buf64); if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err))) return INLINE_SYSCALL_ERROR_RETURN_VALUE (-result); else return __xstat32_conv (vers, &buf64, buf); } }
/* Get information about the file FD in BUF. */ int __fxstat (int vers, int fd, struct stat *buf) { int result; if (vers == _STAT_VER_KERNEL) return INLINE_SYSCALL (fstat, 2, fd, buf); { struct stat64 buf64; INTERNAL_SYSCALL_DECL (err); result = INTERNAL_SYSCALL (fstat64, err, 2, fd, &buf64); if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err))) return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result, err)); else return __xstat32_conv (vers, &buf64, buf); } }
LINKAGE int ADJTIME (const struct TIMEVAL *itv, struct TIMEVAL *otv) { struct TIMEX tntx; if (itv) { struct TIMEVAL tmp; /* We will do some check here. */ tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L; tmp.tv_usec = itv->tv_usec % 1000000L; if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L; tntx.modes = ADJ_OFFSET_SINGLESHOT; } else tntx.modes = ADJ_OFFSET_SS_READ; if (__glibc_unlikely (ADJTIMEX (&tntx) < 0)) return -1; if (otv) { if (tntx.offset < 0) { otv->tv_usec = -(-tntx.offset % 1000000); otv->tv_sec = -(-tntx.offset / 1000000); } else { otv->tv_usec = tntx.offset % 1000000; otv->tv_sec = tntx.offset / 1000000; } } return 0; }
/* Get information about the file NAME in BUF. */ int __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag) { int result; INTERNAL_SYSCALL_DECL (err); #ifdef STAT_IS_KERNEL_STAT # define kst (*st) #else struct kernel_stat kst; #endif result = INTERNAL_SYSCALL (newfstatat, err, 4, fd, file, &kst, flag); if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1)) { #ifdef STAT_IS_KERNEL_STAT return 0; #else return __xstat_conv (vers, &kst, st); #endif } else return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result, err)); }