130ca2051SWilly Tarreau /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 230ca2051SWilly Tarreau /* nolibc.h 330ca2051SWilly Tarreau * Copyright (C) 2017-2018 Willy Tarreau <w@1wt.eu> 430ca2051SWilly Tarreau */ 530ca2051SWilly Tarreau 630ca2051SWilly Tarreau /* 730ca2051SWilly Tarreau * This file is designed to be used as a libc alternative for minimal programs 830ca2051SWilly Tarreau * with very limited requirements. It consists of a small number of syscall and 930ca2051SWilly Tarreau * type definitions, and the minimal startup code needed to call main(). 1030ca2051SWilly Tarreau * All syscalls are declared as static functions so that they can be optimized 1130ca2051SWilly Tarreau * away by the compiler when not used. 1230ca2051SWilly Tarreau * 1330ca2051SWilly Tarreau * Syscalls are split into 3 levels: 1430ca2051SWilly Tarreau * - The lower level is the arch-specific syscall() definition, consisting in 1530ca2051SWilly Tarreau * assembly code in compound expressions. These are called my_syscall0() to 1630ca2051SWilly Tarreau * my_syscall6() depending on the number of arguments. The MIPS 1730ca2051SWilly Tarreau * implementation is limited to 5 arguments. All input arguments are cast 1830ca2051SWilly Tarreau * to a long stored in a register. These expressions always return the 1930ca2051SWilly Tarreau * syscall's return value as a signed long value which is often either a 2030ca2051SWilly Tarreau * pointer or the negated errno value. 2130ca2051SWilly Tarreau * 2230ca2051SWilly Tarreau * - The second level is mostly architecture-independent. It is made of 2330ca2051SWilly Tarreau * static functions called sys_<name>() which rely on my_syscallN() 2430ca2051SWilly Tarreau * depending on the syscall definition. These functions are responsible 2530ca2051SWilly Tarreau * for exposing the appropriate types for the syscall arguments (int, 2630ca2051SWilly Tarreau * pointers, etc) and for setting the appropriate return type (often int). 2730ca2051SWilly Tarreau * A few of them are architecture-specific because the syscalls are not all 2830ca2051SWilly Tarreau * mapped exactly the same among architectures. For example, some archs do 2930ca2051SWilly Tarreau * not implement select() and need pselect6() instead, so the sys_select() 3030ca2051SWilly Tarreau * function will have to abstract this. 3130ca2051SWilly Tarreau * 3230ca2051SWilly Tarreau * - The third level is the libc call definition. It exposes the lower raw 3330ca2051SWilly Tarreau * sys_<name>() calls in a way that looks like what a libc usually does, 3430ca2051SWilly Tarreau * takes care of specific input values, and of setting errno upon error. 3530ca2051SWilly Tarreau * There can be minor variations compared to standard libc calls. For 3630ca2051SWilly Tarreau * example the open() call always takes 3 args here. 3730ca2051SWilly Tarreau * 3830ca2051SWilly Tarreau * The errno variable is declared static and unused. This way it can be 3930ca2051SWilly Tarreau * optimized away if not used. However this means that a program made of 4030ca2051SWilly Tarreau * multiple C files may observe different errno values (one per C file). For 4130ca2051SWilly Tarreau * the type of programs this project targets it usually is not a problem. The 4230ca2051SWilly Tarreau * resulting program may even be reduced by defining the NOLIBC_IGNORE_ERRNO 4330ca2051SWilly Tarreau * macro, in which case the errno value will never be assigned. 4430ca2051SWilly Tarreau * 4530ca2051SWilly Tarreau * Some stdint-like integer types are defined. These are valid on all currently 4630ca2051SWilly Tarreau * supported architectures, because signs are enforced, ints are assumed to be 4730ca2051SWilly Tarreau * 32 bits, longs the size of a pointer and long long 64 bits. If more 4830ca2051SWilly Tarreau * architectures have to be supported, this may need to be adapted. 4930ca2051SWilly Tarreau * 5030ca2051SWilly Tarreau * Some macro definitions like the O_* values passed to open(), and some 5130ca2051SWilly Tarreau * structures like the sys_stat struct depend on the architecture. 5230ca2051SWilly Tarreau * 5330ca2051SWilly Tarreau * The definitions start with the architecture-specific parts, which are picked 5430ca2051SWilly Tarreau * based on what the compiler knows about the target architecture, and are 5530ca2051SWilly Tarreau * completed with the generic code. Since it is the compiler which sets the 5630ca2051SWilly Tarreau * target architecture, cross-compiling normally works out of the box without 5730ca2051SWilly Tarreau * having to specify anything. 5830ca2051SWilly Tarreau * 5930ca2051SWilly Tarreau * Finally some very common libc-level functions are provided. It is the case 6030ca2051SWilly Tarreau * for a few functions usually found in string.h, ctype.h, or stdlib.h. Nothing 6130ca2051SWilly Tarreau * is currently provided regarding stdio emulation. 6230ca2051SWilly Tarreau * 6330ca2051SWilly Tarreau * The macro NOLIBC is always defined, so that it is possible for a program to 6430ca2051SWilly Tarreau * check this macro to know if it is being built against and decide to disable 6530ca2051SWilly Tarreau * some features or simply not to include some standard libc files. 6630ca2051SWilly Tarreau * 6730ca2051SWilly Tarreau * Ideally this file should be split in multiple files for easier long term 6830ca2051SWilly Tarreau * maintenance, but provided as a single file as it is now, it's quite 6930ca2051SWilly Tarreau * convenient to use. Maybe some variations involving a set of includes at the 7030ca2051SWilly Tarreau * top could work. 7130ca2051SWilly Tarreau * 7230ca2051SWilly Tarreau * A simple static executable may be built this way : 7330ca2051SWilly Tarreau * $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \ 743c6ce7a5SWilly Tarreau * -static -include nolibc.h -o hello hello.c -lgcc 7530ca2051SWilly Tarreau * 7630ca2051SWilly Tarreau * A very useful calling convention table may be found here : 7730ca2051SWilly Tarreau * http://man7.org/linux/man-pages/man2/syscall.2.html 7830ca2051SWilly Tarreau * 7930ca2051SWilly Tarreau * This doc is quite convenient though not necessarily up to date : 8030ca2051SWilly Tarreau * https://w3challs.com/syscalls/ 8130ca2051SWilly Tarreau * 8230ca2051SWilly Tarreau */ 83930c4accSWilly Tarreau #ifndef _NOLIBC_H 84930c4accSWilly Tarreau #define _NOLIBC_H 8530ca2051SWilly Tarreau 86967cce19SWilly Tarreau /* standard type definitions */ 87967cce19SWilly Tarreau #include "std.h" 88967cce19SWilly Tarreau 89967cce19SWilly Tarreau /* system includes */ 9030ca2051SWilly Tarreau #include <asm/unistd.h> 91967cce19SWilly Tarreau #include <asm/signal.h> // for SIGCHLD 9230ca2051SWilly Tarreau #include <asm/ioctls.h> 9330ca2051SWilly Tarreau #include <asm/errno.h> 9430ca2051SWilly Tarreau #include <linux/fs.h> 9530ca2051SWilly Tarreau #include <linux/loop.h> 9670ca7aeaSWilly Tarreau #include <linux/time.h> 97*271661c1SWilly Tarreau #include "arch.h" 98cc7a492aSWilly Tarreau #include "types.h" 9930ca2051SWilly Tarreau 100cc7a492aSWilly Tarreau /* Used by programs to avoid std includes */ 10130ca2051SWilly Tarreau #define NOLIBC 10230ca2051SWilly Tarreau 10330ca2051SWilly Tarreau /* this way it will be removed if unused */ 10430ca2051SWilly Tarreau static int errno; 10530ca2051SWilly Tarreau 10630ca2051SWilly Tarreau #ifndef NOLIBC_IGNORE_ERRNO 10730ca2051SWilly Tarreau #define SET_ERRNO(v) do { errno = (v); } while (0) 10830ca2051SWilly Tarreau #else 10930ca2051SWilly Tarreau #define SET_ERRNO(v) do { } while (0) 11030ca2051SWilly Tarreau #endif 11130ca2051SWilly Tarreau 11230ca2051SWilly Tarreau /* errno codes all ensure that they will not conflict with a valid pointer 11306dc8d45SBhaskar Chowdhury * because they all correspond to the highest addressable memory page. 11430ca2051SWilly Tarreau */ 11530ca2051SWilly Tarreau #define MAX_ERRNO 4095 11630ca2051SWilly Tarreau 11730ca2051SWilly Tarreau 11830ca2051SWilly Tarreau /* Below are the C functions used to declare the raw syscalls. They try to be 11930ca2051SWilly Tarreau * architecture-agnostic, and return either a success or -errno. Declaring them 12030ca2051SWilly Tarreau * static will lead to them being inlined in most cases, but it's still possible 12130ca2051SWilly Tarreau * to reference them by a pointer if needed. 12230ca2051SWilly Tarreau */ 12330ca2051SWilly Tarreau static __attribute__((unused)) 12430ca2051SWilly Tarreau void *sys_brk(void *addr) 12530ca2051SWilly Tarreau { 12630ca2051SWilly Tarreau return (void *)my_syscall1(__NR_brk, addr); 12730ca2051SWilly Tarreau } 12830ca2051SWilly Tarreau 12930ca2051SWilly Tarreau static __attribute__((noreturn,unused)) 13030ca2051SWilly Tarreau void sys_exit(int status) 13130ca2051SWilly Tarreau { 13230ca2051SWilly Tarreau my_syscall1(__NR_exit, status & 255); 13330ca2051SWilly Tarreau while(1); // shut the "noreturn" warnings. 13430ca2051SWilly Tarreau } 13530ca2051SWilly Tarreau 13630ca2051SWilly Tarreau static __attribute__((unused)) 13730ca2051SWilly Tarreau int sys_chdir(const char *path) 13830ca2051SWilly Tarreau { 13930ca2051SWilly Tarreau return my_syscall1(__NR_chdir, path); 14030ca2051SWilly Tarreau } 14130ca2051SWilly Tarreau 14230ca2051SWilly Tarreau static __attribute__((unused)) 14330ca2051SWilly Tarreau int sys_chmod(const char *path, mode_t mode) 14430ca2051SWilly Tarreau { 14530ca2051SWilly Tarreau #ifdef __NR_fchmodat 14630ca2051SWilly Tarreau return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); 14735635d7fSWilly Tarreau #elif defined(__NR_chmod) 14830ca2051SWilly Tarreau return my_syscall2(__NR_chmod, path, mode); 14935635d7fSWilly Tarreau #else 15035635d7fSWilly Tarreau #error Neither __NR_fchmodat nor __NR_chmod defined, cannot implement sys_chmod() 15130ca2051SWilly Tarreau #endif 15230ca2051SWilly Tarreau } 15330ca2051SWilly Tarreau 15430ca2051SWilly Tarreau static __attribute__((unused)) 15530ca2051SWilly Tarreau int sys_chown(const char *path, uid_t owner, gid_t group) 15630ca2051SWilly Tarreau { 15730ca2051SWilly Tarreau #ifdef __NR_fchownat 15830ca2051SWilly Tarreau return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); 15935635d7fSWilly Tarreau #elif defined(__NR_chown) 16030ca2051SWilly Tarreau return my_syscall3(__NR_chown, path, owner, group); 16135635d7fSWilly Tarreau #else 16235635d7fSWilly Tarreau #error Neither __NR_fchownat nor __NR_chown defined, cannot implement sys_chown() 16330ca2051SWilly Tarreau #endif 16430ca2051SWilly Tarreau } 16530ca2051SWilly Tarreau 16630ca2051SWilly Tarreau static __attribute__((unused)) 16730ca2051SWilly Tarreau int sys_chroot(const char *path) 16830ca2051SWilly Tarreau { 16930ca2051SWilly Tarreau return my_syscall1(__NR_chroot, path); 17030ca2051SWilly Tarreau } 17130ca2051SWilly Tarreau 17230ca2051SWilly Tarreau static __attribute__((unused)) 17330ca2051SWilly Tarreau int sys_close(int fd) 17430ca2051SWilly Tarreau { 17530ca2051SWilly Tarreau return my_syscall1(__NR_close, fd); 17630ca2051SWilly Tarreau } 17730ca2051SWilly Tarreau 17830ca2051SWilly Tarreau static __attribute__((unused)) 17930ca2051SWilly Tarreau int sys_dup(int fd) 18030ca2051SWilly Tarreau { 18130ca2051SWilly Tarreau return my_syscall1(__NR_dup, fd); 18230ca2051SWilly Tarreau } 18330ca2051SWilly Tarreau 18479f220e5SWilly Tarreau #ifdef __NR_dup3 18579f220e5SWilly Tarreau static __attribute__((unused)) 18679f220e5SWilly Tarreau int sys_dup3(int old, int new, int flags) 18779f220e5SWilly Tarreau { 18879f220e5SWilly Tarreau return my_syscall3(__NR_dup3, old, new, flags); 18979f220e5SWilly Tarreau } 19079f220e5SWilly Tarreau #endif 19179f220e5SWilly Tarreau 19230ca2051SWilly Tarreau static __attribute__((unused)) 19330ca2051SWilly Tarreau int sys_dup2(int old, int new) 19430ca2051SWilly Tarreau { 19579f220e5SWilly Tarreau #ifdef __NR_dup3 19679f220e5SWilly Tarreau return my_syscall3(__NR_dup3, old, new, 0); 19735635d7fSWilly Tarreau #elif defined(__NR_dup2) 19830ca2051SWilly Tarreau return my_syscall2(__NR_dup2, old, new); 19935635d7fSWilly Tarreau #else 20035635d7fSWilly Tarreau #error Neither __NR_dup3 nor __NR_dup2 defined, cannot implement sys_dup2() 20179f220e5SWilly Tarreau #endif 20230ca2051SWilly Tarreau } 20330ca2051SWilly Tarreau 20430ca2051SWilly Tarreau static __attribute__((unused)) 20530ca2051SWilly Tarreau int sys_execve(const char *filename, char *const argv[], char *const envp[]) 20630ca2051SWilly Tarreau { 20730ca2051SWilly Tarreau return my_syscall3(__NR_execve, filename, argv, envp); 20830ca2051SWilly Tarreau } 20930ca2051SWilly Tarreau 21030ca2051SWilly Tarreau static __attribute__((unused)) 21130ca2051SWilly Tarreau pid_t sys_fork(void) 21230ca2051SWilly Tarreau { 213be60ca41SWilly Tarreau #ifdef __NR_clone 214be60ca41SWilly Tarreau /* note: some archs only have clone() and not fork(). Different archs 215be60ca41SWilly Tarreau * have a different API, but most archs have the flags on first arg and 216be60ca41SWilly Tarreau * will not use the rest with no other flag. 217be60ca41SWilly Tarreau */ 218be60ca41SWilly Tarreau return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); 21935635d7fSWilly Tarreau #elif defined(__NR_fork) 22030ca2051SWilly Tarreau return my_syscall0(__NR_fork); 22135635d7fSWilly Tarreau #else 22235635d7fSWilly Tarreau #error Neither __NR_clone nor __NR_fork defined, cannot implement sys_fork() 223be60ca41SWilly Tarreau #endif 22430ca2051SWilly Tarreau } 22530ca2051SWilly Tarreau 22630ca2051SWilly Tarreau static __attribute__((unused)) 22730ca2051SWilly Tarreau int sys_fsync(int fd) 22830ca2051SWilly Tarreau { 22930ca2051SWilly Tarreau return my_syscall1(__NR_fsync, fd); 23030ca2051SWilly Tarreau } 23130ca2051SWilly Tarreau 23230ca2051SWilly Tarreau static __attribute__((unused)) 23330ca2051SWilly Tarreau int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 23430ca2051SWilly Tarreau { 23530ca2051SWilly Tarreau return my_syscall3(__NR_getdents64, fd, dirp, count); 23630ca2051SWilly Tarreau } 23730ca2051SWilly Tarreau 23830ca2051SWilly Tarreau static __attribute__((unused)) 239c0c7c103SWilly Tarreau pid_t sys_getpgid(pid_t pid) 240c0c7c103SWilly Tarreau { 241c0c7c103SWilly Tarreau return my_syscall1(__NR_getpgid, pid); 242c0c7c103SWilly Tarreau } 243c0c7c103SWilly Tarreau 244c0c7c103SWilly Tarreau static __attribute__((unused)) 24530ca2051SWilly Tarreau pid_t sys_getpgrp(void) 24630ca2051SWilly Tarreau { 247c0c7c103SWilly Tarreau return sys_getpgid(0); 24830ca2051SWilly Tarreau } 24930ca2051SWilly Tarreau 25030ca2051SWilly Tarreau static __attribute__((unused)) 25130ca2051SWilly Tarreau pid_t sys_getpid(void) 25230ca2051SWilly Tarreau { 25330ca2051SWilly Tarreau return my_syscall0(__NR_getpid); 25430ca2051SWilly Tarreau } 25530ca2051SWilly Tarreau 25630ca2051SWilly Tarreau static __attribute__((unused)) 257b0fe9decSMark Brown pid_t sys_gettid(void) 258b0fe9decSMark Brown { 259b0fe9decSMark Brown return my_syscall0(__NR_gettid); 260b0fe9decSMark Brown } 261b0fe9decSMark Brown 262b0fe9decSMark Brown static __attribute__((unused)) 26330ca2051SWilly Tarreau int sys_gettimeofday(struct timeval *tv, struct timezone *tz) 26430ca2051SWilly Tarreau { 26530ca2051SWilly Tarreau return my_syscall2(__NR_gettimeofday, tv, tz); 26630ca2051SWilly Tarreau } 26730ca2051SWilly Tarreau 26830ca2051SWilly Tarreau static __attribute__((unused)) 26930ca2051SWilly Tarreau int sys_ioctl(int fd, unsigned long req, void *value) 27030ca2051SWilly Tarreau { 27130ca2051SWilly Tarreau return my_syscall3(__NR_ioctl, fd, req, value); 27230ca2051SWilly Tarreau } 27330ca2051SWilly Tarreau 27430ca2051SWilly Tarreau static __attribute__((unused)) 27530ca2051SWilly Tarreau int sys_kill(pid_t pid, int signal) 27630ca2051SWilly Tarreau { 27730ca2051SWilly Tarreau return my_syscall2(__NR_kill, pid, signal); 27830ca2051SWilly Tarreau } 27930ca2051SWilly Tarreau 28030ca2051SWilly Tarreau static __attribute__((unused)) 28130ca2051SWilly Tarreau int sys_link(const char *old, const char *new) 28230ca2051SWilly Tarreau { 28330ca2051SWilly Tarreau #ifdef __NR_linkat 28430ca2051SWilly Tarreau return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 28535635d7fSWilly Tarreau #elif defined(__NR_link) 28630ca2051SWilly Tarreau return my_syscall2(__NR_link, old, new); 28735635d7fSWilly Tarreau #else 28835635d7fSWilly Tarreau #error Neither __NR_linkat nor __NR_link defined, cannot implement sys_link() 28930ca2051SWilly Tarreau #endif 29030ca2051SWilly Tarreau } 29130ca2051SWilly Tarreau 29230ca2051SWilly Tarreau static __attribute__((unused)) 29330ca2051SWilly Tarreau off_t sys_lseek(int fd, off_t offset, int whence) 29430ca2051SWilly Tarreau { 29530ca2051SWilly Tarreau return my_syscall3(__NR_lseek, fd, offset, whence); 29630ca2051SWilly Tarreau } 29730ca2051SWilly Tarreau 29830ca2051SWilly Tarreau static __attribute__((unused)) 29930ca2051SWilly Tarreau int sys_mkdir(const char *path, mode_t mode) 30030ca2051SWilly Tarreau { 30130ca2051SWilly Tarreau #ifdef __NR_mkdirat 30230ca2051SWilly Tarreau return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 30335635d7fSWilly Tarreau #elif defined(__NR_mkdir) 30430ca2051SWilly Tarreau return my_syscall2(__NR_mkdir, path, mode); 30535635d7fSWilly Tarreau #else 30635635d7fSWilly Tarreau #error Neither __NR_mkdirat nor __NR_mkdir defined, cannot implement sys_mkdir() 30730ca2051SWilly Tarreau #endif 30830ca2051SWilly Tarreau } 30930ca2051SWilly Tarreau 31030ca2051SWilly Tarreau static __attribute__((unused)) 31130ca2051SWilly Tarreau long sys_mknod(const char *path, mode_t mode, dev_t dev) 31230ca2051SWilly Tarreau { 31330ca2051SWilly Tarreau #ifdef __NR_mknodat 31430ca2051SWilly Tarreau return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 31535635d7fSWilly Tarreau #elif defined(__NR_mknod) 31630ca2051SWilly Tarreau return my_syscall3(__NR_mknod, path, mode, dev); 31735635d7fSWilly Tarreau #else 31835635d7fSWilly Tarreau #error Neither __NR_mknodat nor __NR_mknod defined, cannot implement sys_mknod() 31930ca2051SWilly Tarreau #endif 32030ca2051SWilly Tarreau } 32130ca2051SWilly Tarreau 32230ca2051SWilly Tarreau static __attribute__((unused)) 32330ca2051SWilly Tarreau int sys_mount(const char *src, const char *tgt, const char *fst, 32430ca2051SWilly Tarreau unsigned long flags, const void *data) 32530ca2051SWilly Tarreau { 32630ca2051SWilly Tarreau return my_syscall5(__NR_mount, src, tgt, fst, flags, data); 32730ca2051SWilly Tarreau } 32830ca2051SWilly Tarreau 32930ca2051SWilly Tarreau static __attribute__((unused)) 33030ca2051SWilly Tarreau int sys_open(const char *path, int flags, mode_t mode) 33130ca2051SWilly Tarreau { 33230ca2051SWilly Tarreau #ifdef __NR_openat 33330ca2051SWilly Tarreau return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); 33435635d7fSWilly Tarreau #elif defined(__NR_open) 33530ca2051SWilly Tarreau return my_syscall3(__NR_open, path, flags, mode); 33635635d7fSWilly Tarreau #else 33735635d7fSWilly Tarreau #error Neither __NR_openat nor __NR_open defined, cannot implement sys_open() 33830ca2051SWilly Tarreau #endif 33930ca2051SWilly Tarreau } 34030ca2051SWilly Tarreau 34130ca2051SWilly Tarreau static __attribute__((unused)) 34230ca2051SWilly Tarreau int sys_pivot_root(const char *new, const char *old) 34330ca2051SWilly Tarreau { 34430ca2051SWilly Tarreau return my_syscall2(__NR_pivot_root, new, old); 34530ca2051SWilly Tarreau } 34630ca2051SWilly Tarreau 34730ca2051SWilly Tarreau static __attribute__((unused)) 34830ca2051SWilly Tarreau int sys_poll(struct pollfd *fds, int nfds, int timeout) 34930ca2051SWilly Tarreau { 3505b1c827cSWilly Tarreau #if defined(__NR_ppoll) 3515b1c827cSWilly Tarreau struct timespec t; 3525b1c827cSWilly Tarreau 3535b1c827cSWilly Tarreau if (timeout >= 0) { 3545b1c827cSWilly Tarreau t.tv_sec = timeout / 1000; 3555b1c827cSWilly Tarreau t.tv_nsec = (timeout % 1000) * 1000000; 3565b1c827cSWilly Tarreau } 3575b1c827cSWilly Tarreau return my_syscall4(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL); 35835635d7fSWilly Tarreau #elif defined(__NR_poll) 35930ca2051SWilly Tarreau return my_syscall3(__NR_poll, fds, nfds, timeout); 36035635d7fSWilly Tarreau #else 36135635d7fSWilly Tarreau #error Neither __NR_ppoll nor __NR_poll defined, cannot implement sys_poll() 3625b1c827cSWilly Tarreau #endif 36330ca2051SWilly Tarreau } 36430ca2051SWilly Tarreau 36530ca2051SWilly Tarreau static __attribute__((unused)) 36630ca2051SWilly Tarreau ssize_t sys_read(int fd, void *buf, size_t count) 36730ca2051SWilly Tarreau { 36830ca2051SWilly Tarreau return my_syscall3(__NR_read, fd, buf, count); 36930ca2051SWilly Tarreau } 37030ca2051SWilly Tarreau 37130ca2051SWilly Tarreau static __attribute__((unused)) 37230ca2051SWilly Tarreau ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) 37330ca2051SWilly Tarreau { 37430ca2051SWilly Tarreau return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); 37530ca2051SWilly Tarreau } 37630ca2051SWilly Tarreau 37730ca2051SWilly Tarreau static __attribute__((unused)) 37830ca2051SWilly Tarreau int sys_sched_yield(void) 37930ca2051SWilly Tarreau { 38030ca2051SWilly Tarreau return my_syscall0(__NR_sched_yield); 38130ca2051SWilly Tarreau } 38230ca2051SWilly Tarreau 38330ca2051SWilly Tarreau static __attribute__((unused)) 38430ca2051SWilly Tarreau int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 38530ca2051SWilly Tarreau { 38630ca2051SWilly Tarreau #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) 38730ca2051SWilly Tarreau struct sel_arg_struct { 38830ca2051SWilly Tarreau unsigned long n; 38930ca2051SWilly Tarreau fd_set *r, *w, *e; 39030ca2051SWilly Tarreau struct timeval *t; 39130ca2051SWilly Tarreau } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; 39230ca2051SWilly Tarreau return my_syscall1(__NR_select, &arg); 39330ca2051SWilly Tarreau #elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6) 39430ca2051SWilly Tarreau struct timespec t; 39530ca2051SWilly Tarreau 39630ca2051SWilly Tarreau if (timeout) { 39730ca2051SWilly Tarreau t.tv_sec = timeout->tv_sec; 39830ca2051SWilly Tarreau t.tv_nsec = timeout->tv_usec * 1000; 39930ca2051SWilly Tarreau } 40030ca2051SWilly Tarreau return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 40135635d7fSWilly Tarreau #elif defined(__NR__newselect) || defined(__NR_select) 40230ca2051SWilly Tarreau #ifndef __NR__newselect 40330ca2051SWilly Tarreau #define __NR__newselect __NR_select 40430ca2051SWilly Tarreau #endif 40530ca2051SWilly Tarreau return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); 40635635d7fSWilly Tarreau #else 40735635d7fSWilly Tarreau #error None of __NR_select, __NR_pselect6, nor __NR__newselect defined, cannot implement sys_select() 40830ca2051SWilly Tarreau #endif 40930ca2051SWilly Tarreau } 41030ca2051SWilly Tarreau 41130ca2051SWilly Tarreau static __attribute__((unused)) 41230ca2051SWilly Tarreau int sys_setpgid(pid_t pid, pid_t pgid) 41330ca2051SWilly Tarreau { 41430ca2051SWilly Tarreau return my_syscall2(__NR_setpgid, pid, pgid); 41530ca2051SWilly Tarreau } 41630ca2051SWilly Tarreau 41730ca2051SWilly Tarreau static __attribute__((unused)) 41830ca2051SWilly Tarreau pid_t sys_setsid(void) 41930ca2051SWilly Tarreau { 42030ca2051SWilly Tarreau return my_syscall0(__NR_setsid); 42130ca2051SWilly Tarreau } 42230ca2051SWilly Tarreau 42330ca2051SWilly Tarreau static __attribute__((unused)) 42430ca2051SWilly Tarreau int sys_stat(const char *path, struct stat *buf) 42530ca2051SWilly Tarreau { 42630ca2051SWilly Tarreau struct sys_stat_struct stat; 42730ca2051SWilly Tarreau long ret; 42830ca2051SWilly Tarreau 42930ca2051SWilly Tarreau #ifdef __NR_newfstatat 43030ca2051SWilly Tarreau /* only solution for arm64 */ 43130ca2051SWilly Tarreau ret = my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0); 43235635d7fSWilly Tarreau #elif defined(__NR_stat) 43330ca2051SWilly Tarreau ret = my_syscall2(__NR_stat, path, &stat); 43435635d7fSWilly Tarreau #else 43535635d7fSWilly Tarreau #error Neither __NR_newfstatat nor __NR_stat defined, cannot implement sys_stat() 43630ca2051SWilly Tarreau #endif 43730ca2051SWilly Tarreau buf->st_dev = stat.st_dev; 43830ca2051SWilly Tarreau buf->st_ino = stat.st_ino; 43930ca2051SWilly Tarreau buf->st_mode = stat.st_mode; 44030ca2051SWilly Tarreau buf->st_nlink = stat.st_nlink; 44130ca2051SWilly Tarreau buf->st_uid = stat.st_uid; 44230ca2051SWilly Tarreau buf->st_gid = stat.st_gid; 44330ca2051SWilly Tarreau buf->st_rdev = stat.st_rdev; 44430ca2051SWilly Tarreau buf->st_size = stat.st_size; 44530ca2051SWilly Tarreau buf->st_blksize = stat.st_blksize; 44630ca2051SWilly Tarreau buf->st_blocks = stat.st_blocks; 44730ca2051SWilly Tarreau buf->st_atime = stat.st_atime; 44830ca2051SWilly Tarreau buf->st_mtime = stat.st_mtime; 44930ca2051SWilly Tarreau buf->st_ctime = stat.st_ctime; 45030ca2051SWilly Tarreau return ret; 45130ca2051SWilly Tarreau } 45230ca2051SWilly Tarreau 45330ca2051SWilly Tarreau 45430ca2051SWilly Tarreau static __attribute__((unused)) 45530ca2051SWilly Tarreau int sys_symlink(const char *old, const char *new) 45630ca2051SWilly Tarreau { 45730ca2051SWilly Tarreau #ifdef __NR_symlinkat 45830ca2051SWilly Tarreau return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 45935635d7fSWilly Tarreau #elif defined(__NR_symlink) 46030ca2051SWilly Tarreau return my_syscall2(__NR_symlink, old, new); 46135635d7fSWilly Tarreau #else 46235635d7fSWilly Tarreau #error Neither __NR_symlinkat nor __NR_symlink defined, cannot implement sys_symlink() 46330ca2051SWilly Tarreau #endif 46430ca2051SWilly Tarreau } 46530ca2051SWilly Tarreau 46630ca2051SWilly Tarreau static __attribute__((unused)) 46730ca2051SWilly Tarreau mode_t sys_umask(mode_t mode) 46830ca2051SWilly Tarreau { 46930ca2051SWilly Tarreau return my_syscall1(__NR_umask, mode); 47030ca2051SWilly Tarreau } 47130ca2051SWilly Tarreau 47230ca2051SWilly Tarreau static __attribute__((unused)) 47330ca2051SWilly Tarreau int sys_umount2(const char *path, int flags) 47430ca2051SWilly Tarreau { 47530ca2051SWilly Tarreau return my_syscall2(__NR_umount2, path, flags); 47630ca2051SWilly Tarreau } 47730ca2051SWilly Tarreau 47830ca2051SWilly Tarreau static __attribute__((unused)) 47930ca2051SWilly Tarreau int sys_unlink(const char *path) 48030ca2051SWilly Tarreau { 48130ca2051SWilly Tarreau #ifdef __NR_unlinkat 48230ca2051SWilly Tarreau return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 48335635d7fSWilly Tarreau #elif defined(__NR_unlink) 48430ca2051SWilly Tarreau return my_syscall1(__NR_unlink, path); 48535635d7fSWilly Tarreau #else 48635635d7fSWilly Tarreau #error Neither __NR_unlinkat nor __NR_unlink defined, cannot implement sys_unlink() 48730ca2051SWilly Tarreau #endif 48830ca2051SWilly Tarreau } 48930ca2051SWilly Tarreau 49030ca2051SWilly Tarreau static __attribute__((unused)) 49130ca2051SWilly Tarreau pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) 49230ca2051SWilly Tarreau { 49330ca2051SWilly Tarreau return my_syscall4(__NR_wait4, pid, status, options, rusage); 49430ca2051SWilly Tarreau } 49530ca2051SWilly Tarreau 49630ca2051SWilly Tarreau static __attribute__((unused)) 49730ca2051SWilly Tarreau pid_t sys_waitpid(pid_t pid, int *status, int options) 49830ca2051SWilly Tarreau { 49930ca2051SWilly Tarreau return sys_wait4(pid, status, options, 0); 50030ca2051SWilly Tarreau } 50130ca2051SWilly Tarreau 50230ca2051SWilly Tarreau static __attribute__((unused)) 50330ca2051SWilly Tarreau pid_t sys_wait(int *status) 50430ca2051SWilly Tarreau { 50530ca2051SWilly Tarreau return sys_waitpid(-1, status, 0); 50630ca2051SWilly Tarreau } 50730ca2051SWilly Tarreau 50830ca2051SWilly Tarreau static __attribute__((unused)) 50930ca2051SWilly Tarreau ssize_t sys_write(int fd, const void *buf, size_t count) 51030ca2051SWilly Tarreau { 51130ca2051SWilly Tarreau return my_syscall3(__NR_write, fd, buf, count); 51230ca2051SWilly Tarreau } 51330ca2051SWilly Tarreau 51430ca2051SWilly Tarreau 51530ca2051SWilly Tarreau /* Below are the libc-compatible syscalls which return x or -1 and set errno. 51630ca2051SWilly Tarreau * They rely on the functions above. Similarly they're marked static so that it 51730ca2051SWilly Tarreau * is possible to assign pointers to them if needed. 51830ca2051SWilly Tarreau */ 51930ca2051SWilly Tarreau 52030ca2051SWilly Tarreau static __attribute__((unused)) 52130ca2051SWilly Tarreau int brk(void *addr) 52230ca2051SWilly Tarreau { 52330ca2051SWilly Tarreau void *ret = sys_brk(addr); 52430ca2051SWilly Tarreau 52530ca2051SWilly Tarreau if (!ret) { 52630ca2051SWilly Tarreau SET_ERRNO(ENOMEM); 52730ca2051SWilly Tarreau return -1; 52830ca2051SWilly Tarreau } 52930ca2051SWilly Tarreau return 0; 53030ca2051SWilly Tarreau } 53130ca2051SWilly Tarreau 53230ca2051SWilly Tarreau static __attribute__((noreturn,unused)) 53330ca2051SWilly Tarreau void exit(int status) 53430ca2051SWilly Tarreau { 53530ca2051SWilly Tarreau sys_exit(status); 53630ca2051SWilly Tarreau } 53730ca2051SWilly Tarreau 53830ca2051SWilly Tarreau static __attribute__((unused)) 53930ca2051SWilly Tarreau int chdir(const char *path) 54030ca2051SWilly Tarreau { 54130ca2051SWilly Tarreau int ret = sys_chdir(path); 54230ca2051SWilly Tarreau 54330ca2051SWilly Tarreau if (ret < 0) { 54430ca2051SWilly Tarreau SET_ERRNO(-ret); 54530ca2051SWilly Tarreau ret = -1; 54630ca2051SWilly Tarreau } 54730ca2051SWilly Tarreau return ret; 54830ca2051SWilly Tarreau } 54930ca2051SWilly Tarreau 55030ca2051SWilly Tarreau static __attribute__((unused)) 55130ca2051SWilly Tarreau int chmod(const char *path, mode_t mode) 55230ca2051SWilly Tarreau { 55330ca2051SWilly Tarreau int ret = sys_chmod(path, mode); 55430ca2051SWilly Tarreau 55530ca2051SWilly Tarreau if (ret < 0) { 55630ca2051SWilly Tarreau SET_ERRNO(-ret); 55730ca2051SWilly Tarreau ret = -1; 55830ca2051SWilly Tarreau } 55930ca2051SWilly Tarreau return ret; 56030ca2051SWilly Tarreau } 56130ca2051SWilly Tarreau 56230ca2051SWilly Tarreau static __attribute__((unused)) 56330ca2051SWilly Tarreau int chown(const char *path, uid_t owner, gid_t group) 56430ca2051SWilly Tarreau { 56530ca2051SWilly Tarreau int ret = sys_chown(path, owner, group); 56630ca2051SWilly Tarreau 56730ca2051SWilly Tarreau if (ret < 0) { 56830ca2051SWilly Tarreau SET_ERRNO(-ret); 56930ca2051SWilly Tarreau ret = -1; 57030ca2051SWilly Tarreau } 57130ca2051SWilly Tarreau return ret; 57230ca2051SWilly Tarreau } 57330ca2051SWilly Tarreau 57430ca2051SWilly Tarreau static __attribute__((unused)) 57530ca2051SWilly Tarreau int chroot(const char *path) 57630ca2051SWilly Tarreau { 57730ca2051SWilly Tarreau int ret = sys_chroot(path); 57830ca2051SWilly Tarreau 57930ca2051SWilly Tarreau if (ret < 0) { 58030ca2051SWilly Tarreau SET_ERRNO(-ret); 58130ca2051SWilly Tarreau ret = -1; 58230ca2051SWilly Tarreau } 58330ca2051SWilly Tarreau return ret; 58430ca2051SWilly Tarreau } 58530ca2051SWilly Tarreau 58630ca2051SWilly Tarreau static __attribute__((unused)) 58730ca2051SWilly Tarreau int close(int fd) 58830ca2051SWilly Tarreau { 58930ca2051SWilly Tarreau int ret = sys_close(fd); 59030ca2051SWilly Tarreau 59130ca2051SWilly Tarreau if (ret < 0) { 59230ca2051SWilly Tarreau SET_ERRNO(-ret); 59330ca2051SWilly Tarreau ret = -1; 59430ca2051SWilly Tarreau } 59530ca2051SWilly Tarreau return ret; 59630ca2051SWilly Tarreau } 59730ca2051SWilly Tarreau 59830ca2051SWilly Tarreau static __attribute__((unused)) 599c261145aSWilly Tarreau int dup(int fd) 600c261145aSWilly Tarreau { 601c261145aSWilly Tarreau int ret = sys_dup(fd); 602c261145aSWilly Tarreau 603c261145aSWilly Tarreau if (ret < 0) { 604c261145aSWilly Tarreau SET_ERRNO(-ret); 605c261145aSWilly Tarreau ret = -1; 606c261145aSWilly Tarreau } 607c261145aSWilly Tarreau return ret; 608c261145aSWilly Tarreau } 609c261145aSWilly Tarreau 610c261145aSWilly Tarreau static __attribute__((unused)) 61130ca2051SWilly Tarreau int dup2(int old, int new) 61230ca2051SWilly Tarreau { 61330ca2051SWilly Tarreau int ret = sys_dup2(old, new); 61430ca2051SWilly Tarreau 61530ca2051SWilly Tarreau if (ret < 0) { 61630ca2051SWilly Tarreau SET_ERRNO(-ret); 61730ca2051SWilly Tarreau ret = -1; 61830ca2051SWilly Tarreau } 61930ca2051SWilly Tarreau return ret; 62030ca2051SWilly Tarreau } 62130ca2051SWilly Tarreau 62279f220e5SWilly Tarreau #ifdef __NR_dup3 62379f220e5SWilly Tarreau static __attribute__((unused)) 62479f220e5SWilly Tarreau int dup3(int old, int new, int flags) 62579f220e5SWilly Tarreau { 62679f220e5SWilly Tarreau int ret = sys_dup3(old, new, flags); 62779f220e5SWilly Tarreau 62879f220e5SWilly Tarreau if (ret < 0) { 62979f220e5SWilly Tarreau SET_ERRNO(-ret); 63079f220e5SWilly Tarreau ret = -1; 63179f220e5SWilly Tarreau } 63279f220e5SWilly Tarreau return ret; 63379f220e5SWilly Tarreau } 63479f220e5SWilly Tarreau #endif 63579f220e5SWilly Tarreau 63630ca2051SWilly Tarreau static __attribute__((unused)) 63730ca2051SWilly Tarreau int execve(const char *filename, char *const argv[], char *const envp[]) 63830ca2051SWilly Tarreau { 63930ca2051SWilly Tarreau int ret = sys_execve(filename, argv, envp); 64030ca2051SWilly Tarreau 64130ca2051SWilly Tarreau if (ret < 0) { 64230ca2051SWilly Tarreau SET_ERRNO(-ret); 64330ca2051SWilly Tarreau ret = -1; 64430ca2051SWilly Tarreau } 64530ca2051SWilly Tarreau return ret; 64630ca2051SWilly Tarreau } 64730ca2051SWilly Tarreau 64830ca2051SWilly Tarreau static __attribute__((unused)) 64930ca2051SWilly Tarreau pid_t fork(void) 65030ca2051SWilly Tarreau { 65130ca2051SWilly Tarreau pid_t ret = sys_fork(); 65230ca2051SWilly Tarreau 65330ca2051SWilly Tarreau if (ret < 0) { 65430ca2051SWilly Tarreau SET_ERRNO(-ret); 65530ca2051SWilly Tarreau ret = -1; 65630ca2051SWilly Tarreau } 65730ca2051SWilly Tarreau return ret; 65830ca2051SWilly Tarreau } 65930ca2051SWilly Tarreau 66030ca2051SWilly Tarreau static __attribute__((unused)) 66130ca2051SWilly Tarreau int fsync(int fd) 66230ca2051SWilly Tarreau { 66330ca2051SWilly Tarreau int ret = sys_fsync(fd); 66430ca2051SWilly Tarreau 66530ca2051SWilly Tarreau if (ret < 0) { 66630ca2051SWilly Tarreau SET_ERRNO(-ret); 66730ca2051SWilly Tarreau ret = -1; 66830ca2051SWilly Tarreau } 66930ca2051SWilly Tarreau return ret; 67030ca2051SWilly Tarreau } 67130ca2051SWilly Tarreau 67230ca2051SWilly Tarreau static __attribute__((unused)) 67330ca2051SWilly Tarreau int getdents64(int fd, struct linux_dirent64 *dirp, int count) 67430ca2051SWilly Tarreau { 67530ca2051SWilly Tarreau int ret = sys_getdents64(fd, dirp, count); 67630ca2051SWilly Tarreau 67730ca2051SWilly Tarreau if (ret < 0) { 67830ca2051SWilly Tarreau SET_ERRNO(-ret); 67930ca2051SWilly Tarreau ret = -1; 68030ca2051SWilly Tarreau } 68130ca2051SWilly Tarreau return ret; 68230ca2051SWilly Tarreau } 68330ca2051SWilly Tarreau 68430ca2051SWilly Tarreau static __attribute__((unused)) 685c0c7c103SWilly Tarreau pid_t getpgid(pid_t pid) 686c0c7c103SWilly Tarreau { 687c0c7c103SWilly Tarreau pid_t ret = sys_getpgid(pid); 688c0c7c103SWilly Tarreau 689c0c7c103SWilly Tarreau if (ret < 0) { 690c0c7c103SWilly Tarreau SET_ERRNO(-ret); 691c0c7c103SWilly Tarreau ret = -1; 692c0c7c103SWilly Tarreau } 693c0c7c103SWilly Tarreau return ret; 694c0c7c103SWilly Tarreau } 695c0c7c103SWilly Tarreau 696c0c7c103SWilly Tarreau static __attribute__((unused)) 69730ca2051SWilly Tarreau pid_t getpgrp(void) 69830ca2051SWilly Tarreau { 69930ca2051SWilly Tarreau pid_t ret = sys_getpgrp(); 70030ca2051SWilly Tarreau 70130ca2051SWilly Tarreau if (ret < 0) { 70230ca2051SWilly Tarreau SET_ERRNO(-ret); 70330ca2051SWilly Tarreau ret = -1; 70430ca2051SWilly Tarreau } 70530ca2051SWilly Tarreau return ret; 70630ca2051SWilly Tarreau } 70730ca2051SWilly Tarreau 70830ca2051SWilly Tarreau static __attribute__((unused)) 70930ca2051SWilly Tarreau pid_t getpid(void) 71030ca2051SWilly Tarreau { 71130ca2051SWilly Tarreau pid_t ret = sys_getpid(); 71230ca2051SWilly Tarreau 71330ca2051SWilly Tarreau if (ret < 0) { 71430ca2051SWilly Tarreau SET_ERRNO(-ret); 71530ca2051SWilly Tarreau ret = -1; 71630ca2051SWilly Tarreau } 71730ca2051SWilly Tarreau return ret; 71830ca2051SWilly Tarreau } 71930ca2051SWilly Tarreau 72030ca2051SWilly Tarreau static __attribute__((unused)) 721b0fe9decSMark Brown pid_t gettid(void) 722b0fe9decSMark Brown { 723b0fe9decSMark Brown pid_t ret = sys_gettid(); 724b0fe9decSMark Brown 725b0fe9decSMark Brown if (ret < 0) { 726b0fe9decSMark Brown SET_ERRNO(-ret); 727b0fe9decSMark Brown ret = -1; 728b0fe9decSMark Brown } 729b0fe9decSMark Brown return ret; 730b0fe9decSMark Brown } 731b0fe9decSMark Brown 732b0fe9decSMark Brown static __attribute__((unused)) 73330ca2051SWilly Tarreau int gettimeofday(struct timeval *tv, struct timezone *tz) 73430ca2051SWilly Tarreau { 73530ca2051SWilly Tarreau int ret = sys_gettimeofday(tv, tz); 73630ca2051SWilly Tarreau 73730ca2051SWilly Tarreau if (ret < 0) { 73830ca2051SWilly Tarreau SET_ERRNO(-ret); 73930ca2051SWilly Tarreau ret = -1; 74030ca2051SWilly Tarreau } 74130ca2051SWilly Tarreau return ret; 74230ca2051SWilly Tarreau } 74330ca2051SWilly Tarreau 74430ca2051SWilly Tarreau static __attribute__((unused)) 74530ca2051SWilly Tarreau int ioctl(int fd, unsigned long req, void *value) 74630ca2051SWilly Tarreau { 74730ca2051SWilly Tarreau int ret = sys_ioctl(fd, req, value); 74830ca2051SWilly Tarreau 74930ca2051SWilly Tarreau if (ret < 0) { 75030ca2051SWilly Tarreau SET_ERRNO(-ret); 75130ca2051SWilly Tarreau ret = -1; 75230ca2051SWilly Tarreau } 75330ca2051SWilly Tarreau return ret; 75430ca2051SWilly Tarreau } 75530ca2051SWilly Tarreau 75630ca2051SWilly Tarreau static __attribute__((unused)) 75730ca2051SWilly Tarreau int kill(pid_t pid, int signal) 75830ca2051SWilly Tarreau { 75930ca2051SWilly Tarreau int ret = sys_kill(pid, signal); 76030ca2051SWilly Tarreau 76130ca2051SWilly Tarreau if (ret < 0) { 76230ca2051SWilly Tarreau SET_ERRNO(-ret); 76330ca2051SWilly Tarreau ret = -1; 76430ca2051SWilly Tarreau } 76530ca2051SWilly Tarreau return ret; 76630ca2051SWilly Tarreau } 76730ca2051SWilly Tarreau 76830ca2051SWilly Tarreau static __attribute__((unused)) 76930ca2051SWilly Tarreau int link(const char *old, const char *new) 77030ca2051SWilly Tarreau { 77130ca2051SWilly Tarreau int ret = sys_link(old, new); 77230ca2051SWilly Tarreau 77330ca2051SWilly Tarreau if (ret < 0) { 77430ca2051SWilly Tarreau SET_ERRNO(-ret); 77530ca2051SWilly Tarreau ret = -1; 77630ca2051SWilly Tarreau } 77730ca2051SWilly Tarreau return ret; 77830ca2051SWilly Tarreau } 77930ca2051SWilly Tarreau 78030ca2051SWilly Tarreau static __attribute__((unused)) 78130ca2051SWilly Tarreau off_t lseek(int fd, off_t offset, int whence) 78230ca2051SWilly Tarreau { 78330ca2051SWilly Tarreau off_t ret = sys_lseek(fd, offset, whence); 78430ca2051SWilly Tarreau 78530ca2051SWilly Tarreau if (ret < 0) { 78630ca2051SWilly Tarreau SET_ERRNO(-ret); 78730ca2051SWilly Tarreau ret = -1; 78830ca2051SWilly Tarreau } 78930ca2051SWilly Tarreau return ret; 79030ca2051SWilly Tarreau } 79130ca2051SWilly Tarreau 79230ca2051SWilly Tarreau static __attribute__((unused)) 79330ca2051SWilly Tarreau int mkdir(const char *path, mode_t mode) 79430ca2051SWilly Tarreau { 79530ca2051SWilly Tarreau int ret = sys_mkdir(path, mode); 79630ca2051SWilly Tarreau 79730ca2051SWilly Tarreau if (ret < 0) { 79830ca2051SWilly Tarreau SET_ERRNO(-ret); 79930ca2051SWilly Tarreau ret = -1; 80030ca2051SWilly Tarreau } 80130ca2051SWilly Tarreau return ret; 80230ca2051SWilly Tarreau } 80330ca2051SWilly Tarreau 80430ca2051SWilly Tarreau static __attribute__((unused)) 80530ca2051SWilly Tarreau int mknod(const char *path, mode_t mode, dev_t dev) 80630ca2051SWilly Tarreau { 80730ca2051SWilly Tarreau int ret = sys_mknod(path, mode, dev); 80830ca2051SWilly Tarreau 80930ca2051SWilly Tarreau if (ret < 0) { 81030ca2051SWilly Tarreau SET_ERRNO(-ret); 81130ca2051SWilly Tarreau ret = -1; 81230ca2051SWilly Tarreau } 81330ca2051SWilly Tarreau return ret; 81430ca2051SWilly Tarreau } 81530ca2051SWilly Tarreau 81630ca2051SWilly Tarreau static __attribute__((unused)) 81730ca2051SWilly Tarreau int mount(const char *src, const char *tgt, 81830ca2051SWilly Tarreau const char *fst, unsigned long flags, 81930ca2051SWilly Tarreau const void *data) 82030ca2051SWilly Tarreau { 82130ca2051SWilly Tarreau int ret = sys_mount(src, tgt, fst, flags, data); 82230ca2051SWilly Tarreau 82330ca2051SWilly Tarreau if (ret < 0) { 82430ca2051SWilly Tarreau SET_ERRNO(-ret); 82530ca2051SWilly Tarreau ret = -1; 82630ca2051SWilly Tarreau } 82730ca2051SWilly Tarreau return ret; 82830ca2051SWilly Tarreau } 82930ca2051SWilly Tarreau 83030ca2051SWilly Tarreau static __attribute__((unused)) 83130ca2051SWilly Tarreau int open(const char *path, int flags, mode_t mode) 83230ca2051SWilly Tarreau { 83330ca2051SWilly Tarreau int ret = sys_open(path, flags, mode); 83430ca2051SWilly Tarreau 83530ca2051SWilly Tarreau if (ret < 0) { 83630ca2051SWilly Tarreau SET_ERRNO(-ret); 83730ca2051SWilly Tarreau ret = -1; 83830ca2051SWilly Tarreau } 83930ca2051SWilly Tarreau return ret; 84030ca2051SWilly Tarreau } 84130ca2051SWilly Tarreau 84230ca2051SWilly Tarreau static __attribute__((unused)) 84330ca2051SWilly Tarreau int pivot_root(const char *new, const char *old) 84430ca2051SWilly Tarreau { 84530ca2051SWilly Tarreau int ret = sys_pivot_root(new, old); 84630ca2051SWilly Tarreau 84730ca2051SWilly Tarreau if (ret < 0) { 84830ca2051SWilly Tarreau SET_ERRNO(-ret); 84930ca2051SWilly Tarreau ret = -1; 85030ca2051SWilly Tarreau } 85130ca2051SWilly Tarreau return ret; 85230ca2051SWilly Tarreau } 85330ca2051SWilly Tarreau 85430ca2051SWilly Tarreau static __attribute__((unused)) 85530ca2051SWilly Tarreau int poll(struct pollfd *fds, int nfds, int timeout) 85630ca2051SWilly Tarreau { 85730ca2051SWilly Tarreau int ret = sys_poll(fds, nfds, timeout); 85830ca2051SWilly Tarreau 85930ca2051SWilly Tarreau if (ret < 0) { 86030ca2051SWilly Tarreau SET_ERRNO(-ret); 86130ca2051SWilly Tarreau ret = -1; 86230ca2051SWilly Tarreau } 86330ca2051SWilly Tarreau return ret; 86430ca2051SWilly Tarreau } 86530ca2051SWilly Tarreau 86630ca2051SWilly Tarreau static __attribute__((unused)) 86730ca2051SWilly Tarreau ssize_t read(int fd, void *buf, size_t count) 86830ca2051SWilly Tarreau { 86930ca2051SWilly Tarreau ssize_t ret = sys_read(fd, buf, count); 87030ca2051SWilly Tarreau 87130ca2051SWilly Tarreau if (ret < 0) { 87230ca2051SWilly Tarreau SET_ERRNO(-ret); 87330ca2051SWilly Tarreau ret = -1; 87430ca2051SWilly Tarreau } 87530ca2051SWilly Tarreau return ret; 87630ca2051SWilly Tarreau } 87730ca2051SWilly Tarreau 87830ca2051SWilly Tarreau static __attribute__((unused)) 87930ca2051SWilly Tarreau int reboot(int cmd) 88030ca2051SWilly Tarreau { 88130ca2051SWilly Tarreau int ret = sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0); 88230ca2051SWilly Tarreau 88330ca2051SWilly Tarreau if (ret < 0) { 88430ca2051SWilly Tarreau SET_ERRNO(-ret); 88530ca2051SWilly Tarreau ret = -1; 88630ca2051SWilly Tarreau } 88730ca2051SWilly Tarreau return ret; 88830ca2051SWilly Tarreau } 88930ca2051SWilly Tarreau 89030ca2051SWilly Tarreau static __attribute__((unused)) 89130ca2051SWilly Tarreau void *sbrk(intptr_t inc) 89230ca2051SWilly Tarreau { 89330ca2051SWilly Tarreau void *ret; 89430ca2051SWilly Tarreau 89530ca2051SWilly Tarreau /* first call to find current end */ 89630ca2051SWilly Tarreau if ((ret = sys_brk(0)) && (sys_brk(ret + inc) == ret + inc)) 89730ca2051SWilly Tarreau return ret + inc; 89830ca2051SWilly Tarreau 89930ca2051SWilly Tarreau SET_ERRNO(ENOMEM); 90030ca2051SWilly Tarreau return (void *)-1; 90130ca2051SWilly Tarreau } 90230ca2051SWilly Tarreau 90330ca2051SWilly Tarreau static __attribute__((unused)) 90430ca2051SWilly Tarreau int sched_yield(void) 90530ca2051SWilly Tarreau { 90630ca2051SWilly Tarreau int ret = sys_sched_yield(); 90730ca2051SWilly Tarreau 90830ca2051SWilly Tarreau if (ret < 0) { 90930ca2051SWilly Tarreau SET_ERRNO(-ret); 91030ca2051SWilly Tarreau ret = -1; 91130ca2051SWilly Tarreau } 91230ca2051SWilly Tarreau return ret; 91330ca2051SWilly Tarreau } 91430ca2051SWilly Tarreau 91530ca2051SWilly Tarreau static __attribute__((unused)) 91630ca2051SWilly Tarreau int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 91730ca2051SWilly Tarreau { 91830ca2051SWilly Tarreau int ret = sys_select(nfds, rfds, wfds, efds, timeout); 91930ca2051SWilly Tarreau 92030ca2051SWilly Tarreau if (ret < 0) { 92130ca2051SWilly Tarreau SET_ERRNO(-ret); 92230ca2051SWilly Tarreau ret = -1; 92330ca2051SWilly Tarreau } 92430ca2051SWilly Tarreau return ret; 92530ca2051SWilly Tarreau } 92630ca2051SWilly Tarreau 92730ca2051SWilly Tarreau static __attribute__((unused)) 92830ca2051SWilly Tarreau int setpgid(pid_t pid, pid_t pgid) 92930ca2051SWilly Tarreau { 93030ca2051SWilly Tarreau int ret = sys_setpgid(pid, pgid); 93130ca2051SWilly Tarreau 93230ca2051SWilly Tarreau if (ret < 0) { 93330ca2051SWilly Tarreau SET_ERRNO(-ret); 93430ca2051SWilly Tarreau ret = -1; 93530ca2051SWilly Tarreau } 93630ca2051SWilly Tarreau return ret; 93730ca2051SWilly Tarreau } 93830ca2051SWilly Tarreau 93930ca2051SWilly Tarreau static __attribute__((unused)) 94030ca2051SWilly Tarreau pid_t setsid(void) 94130ca2051SWilly Tarreau { 94230ca2051SWilly Tarreau pid_t ret = sys_setsid(); 94330ca2051SWilly Tarreau 94430ca2051SWilly Tarreau if (ret < 0) { 94530ca2051SWilly Tarreau SET_ERRNO(-ret); 94630ca2051SWilly Tarreau ret = -1; 94730ca2051SWilly Tarreau } 94830ca2051SWilly Tarreau return ret; 94930ca2051SWilly Tarreau } 95030ca2051SWilly Tarreau 95130ca2051SWilly Tarreau static __attribute__((unused)) 95230ca2051SWilly Tarreau unsigned int sleep(unsigned int seconds) 95330ca2051SWilly Tarreau { 95430ca2051SWilly Tarreau struct timeval my_timeval = { seconds, 0 }; 95530ca2051SWilly Tarreau 95630ca2051SWilly Tarreau if (sys_select(0, 0, 0, 0, &my_timeval) < 0) 95730ca2051SWilly Tarreau return my_timeval.tv_sec + !!my_timeval.tv_usec; 95830ca2051SWilly Tarreau else 95930ca2051SWilly Tarreau return 0; 96030ca2051SWilly Tarreau } 96130ca2051SWilly Tarreau 96230ca2051SWilly Tarreau static __attribute__((unused)) 963f916d77eSMark Brown int msleep(unsigned int msecs) 964f916d77eSMark Brown { 965f916d77eSMark Brown struct timeval my_timeval = { msecs / 1000, (msecs % 1000) * 1000 }; 966f916d77eSMark Brown 967f916d77eSMark Brown if (sys_select(0, 0, 0, 0, &my_timeval) < 0) 968f916d77eSMark Brown return (my_timeval.tv_sec * 1000) + 969f916d77eSMark Brown (my_timeval.tv_usec / 1000) + 970f916d77eSMark Brown !!(my_timeval.tv_usec % 1000); 971f916d77eSMark Brown else 972f916d77eSMark Brown return 0; 973f916d77eSMark Brown } 974f916d77eSMark Brown 975f916d77eSMark Brown static __attribute__((unused)) 97630ca2051SWilly Tarreau int stat(const char *path, struct stat *buf) 97730ca2051SWilly Tarreau { 97830ca2051SWilly Tarreau int ret = sys_stat(path, buf); 97930ca2051SWilly Tarreau 98030ca2051SWilly Tarreau if (ret < 0) { 98130ca2051SWilly Tarreau SET_ERRNO(-ret); 98230ca2051SWilly Tarreau ret = -1; 98330ca2051SWilly Tarreau } 98430ca2051SWilly Tarreau return ret; 98530ca2051SWilly Tarreau } 98630ca2051SWilly Tarreau 98730ca2051SWilly Tarreau static __attribute__((unused)) 98830ca2051SWilly Tarreau int symlink(const char *old, const char *new) 98930ca2051SWilly Tarreau { 99030ca2051SWilly Tarreau int ret = sys_symlink(old, new); 99130ca2051SWilly Tarreau 99230ca2051SWilly Tarreau if (ret < 0) { 99330ca2051SWilly Tarreau SET_ERRNO(-ret); 99430ca2051SWilly Tarreau ret = -1; 99530ca2051SWilly Tarreau } 99630ca2051SWilly Tarreau return ret; 99730ca2051SWilly Tarreau } 99830ca2051SWilly Tarreau 99930ca2051SWilly Tarreau static __attribute__((unused)) 100030ca2051SWilly Tarreau int tcsetpgrp(int fd, pid_t pid) 100130ca2051SWilly Tarreau { 100230ca2051SWilly Tarreau return ioctl(fd, TIOCSPGRP, &pid); 100330ca2051SWilly Tarreau } 100430ca2051SWilly Tarreau 100530ca2051SWilly Tarreau static __attribute__((unused)) 100630ca2051SWilly Tarreau mode_t umask(mode_t mode) 100730ca2051SWilly Tarreau { 100830ca2051SWilly Tarreau return sys_umask(mode); 100930ca2051SWilly Tarreau } 101030ca2051SWilly Tarreau 101130ca2051SWilly Tarreau static __attribute__((unused)) 101230ca2051SWilly Tarreau int umount2(const char *path, int flags) 101330ca2051SWilly Tarreau { 101430ca2051SWilly Tarreau int ret = sys_umount2(path, flags); 101530ca2051SWilly Tarreau 101630ca2051SWilly Tarreau if (ret < 0) { 101730ca2051SWilly Tarreau SET_ERRNO(-ret); 101830ca2051SWilly Tarreau ret = -1; 101930ca2051SWilly Tarreau } 102030ca2051SWilly Tarreau return ret; 102130ca2051SWilly Tarreau } 102230ca2051SWilly Tarreau 102330ca2051SWilly Tarreau static __attribute__((unused)) 102430ca2051SWilly Tarreau int unlink(const char *path) 102530ca2051SWilly Tarreau { 102630ca2051SWilly Tarreau int ret = sys_unlink(path); 102730ca2051SWilly Tarreau 102830ca2051SWilly Tarreau if (ret < 0) { 102930ca2051SWilly Tarreau SET_ERRNO(-ret); 103030ca2051SWilly Tarreau ret = -1; 103130ca2051SWilly Tarreau } 103230ca2051SWilly Tarreau return ret; 103330ca2051SWilly Tarreau } 103430ca2051SWilly Tarreau 103530ca2051SWilly Tarreau static __attribute__((unused)) 103630ca2051SWilly Tarreau pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) 103730ca2051SWilly Tarreau { 103830ca2051SWilly Tarreau pid_t ret = sys_wait4(pid, status, options, rusage); 103930ca2051SWilly Tarreau 104030ca2051SWilly Tarreau if (ret < 0) { 104130ca2051SWilly Tarreau SET_ERRNO(-ret); 104230ca2051SWilly Tarreau ret = -1; 104330ca2051SWilly Tarreau } 104430ca2051SWilly Tarreau return ret; 104530ca2051SWilly Tarreau } 104630ca2051SWilly Tarreau 104730ca2051SWilly Tarreau static __attribute__((unused)) 104830ca2051SWilly Tarreau pid_t waitpid(pid_t pid, int *status, int options) 104930ca2051SWilly Tarreau { 105030ca2051SWilly Tarreau pid_t ret = sys_waitpid(pid, status, options); 105130ca2051SWilly Tarreau 105230ca2051SWilly Tarreau if (ret < 0) { 105330ca2051SWilly Tarreau SET_ERRNO(-ret); 105430ca2051SWilly Tarreau ret = -1; 105530ca2051SWilly Tarreau } 105630ca2051SWilly Tarreau return ret; 105730ca2051SWilly Tarreau } 105830ca2051SWilly Tarreau 105930ca2051SWilly Tarreau static __attribute__((unused)) 106030ca2051SWilly Tarreau pid_t wait(int *status) 106130ca2051SWilly Tarreau { 106230ca2051SWilly Tarreau pid_t ret = sys_wait(status); 106330ca2051SWilly Tarreau 106430ca2051SWilly Tarreau if (ret < 0) { 106530ca2051SWilly Tarreau SET_ERRNO(-ret); 106630ca2051SWilly Tarreau ret = -1; 106730ca2051SWilly Tarreau } 106830ca2051SWilly Tarreau return ret; 106930ca2051SWilly Tarreau } 107030ca2051SWilly Tarreau 107130ca2051SWilly Tarreau static __attribute__((unused)) 107230ca2051SWilly Tarreau ssize_t write(int fd, const void *buf, size_t count) 107330ca2051SWilly Tarreau { 107430ca2051SWilly Tarreau ssize_t ret = sys_write(fd, buf, count); 107530ca2051SWilly Tarreau 107630ca2051SWilly Tarreau if (ret < 0) { 107730ca2051SWilly Tarreau SET_ERRNO(-ret); 107830ca2051SWilly Tarreau ret = -1; 107930ca2051SWilly Tarreau } 108030ca2051SWilly Tarreau return ret; 108130ca2051SWilly Tarreau } 108230ca2051SWilly Tarreau 108330ca2051SWilly Tarreau /* some size-optimized reimplementations of a few common str* and mem* 108430ca2051SWilly Tarreau * functions. They're marked static, except memcpy() and raise() which are used 108530ca2051SWilly Tarreau * by libgcc on ARM, so they are marked weak instead in order not to cause an 108630ca2051SWilly Tarreau * error when building a program made of multiple files (not recommended). 108730ca2051SWilly Tarreau */ 108830ca2051SWilly Tarreau 108930ca2051SWilly Tarreau static __attribute__((unused)) 109030ca2051SWilly Tarreau void *memmove(void *dst, const void *src, size_t len) 109130ca2051SWilly Tarreau { 109230ca2051SWilly Tarreau ssize_t pos = (dst <= src) ? -1 : (long)len; 109330ca2051SWilly Tarreau void *ret = dst; 109430ca2051SWilly Tarreau 109530ca2051SWilly Tarreau while (len--) { 109630ca2051SWilly Tarreau pos += (dst <= src) ? 1 : -1; 109730ca2051SWilly Tarreau ((char *)dst)[pos] = ((char *)src)[pos]; 109830ca2051SWilly Tarreau } 109930ca2051SWilly Tarreau return ret; 110030ca2051SWilly Tarreau } 110130ca2051SWilly Tarreau 110230ca2051SWilly Tarreau static __attribute__((unused)) 110330ca2051SWilly Tarreau void *memset(void *dst, int b, size_t len) 110430ca2051SWilly Tarreau { 110530ca2051SWilly Tarreau char *p = dst; 110630ca2051SWilly Tarreau 110730ca2051SWilly Tarreau while (len--) 110830ca2051SWilly Tarreau *(p++) = b; 110930ca2051SWilly Tarreau return dst; 111030ca2051SWilly Tarreau } 111130ca2051SWilly Tarreau 111230ca2051SWilly Tarreau static __attribute__((unused)) 111330ca2051SWilly Tarreau int memcmp(const void *s1, const void *s2, size_t n) 111430ca2051SWilly Tarreau { 111530ca2051SWilly Tarreau size_t ofs = 0; 111630ca2051SWilly Tarreau char c1 = 0; 111730ca2051SWilly Tarreau 111830ca2051SWilly Tarreau while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) { 111930ca2051SWilly Tarreau ofs++; 112030ca2051SWilly Tarreau } 112130ca2051SWilly Tarreau return c1; 112230ca2051SWilly Tarreau } 112330ca2051SWilly Tarreau 112430ca2051SWilly Tarreau static __attribute__((unused)) 112530ca2051SWilly Tarreau char *strcpy(char *dst, const char *src) 112630ca2051SWilly Tarreau { 112730ca2051SWilly Tarreau char *ret = dst; 112830ca2051SWilly Tarreau 112930ca2051SWilly Tarreau while ((*dst++ = *src++)); 113030ca2051SWilly Tarreau return ret; 113130ca2051SWilly Tarreau } 113230ca2051SWilly Tarreau 113330ca2051SWilly Tarreau static __attribute__((unused)) 113430ca2051SWilly Tarreau char *strchr(const char *s, int c) 113530ca2051SWilly Tarreau { 113630ca2051SWilly Tarreau while (*s) { 113730ca2051SWilly Tarreau if (*s == (char)c) 113830ca2051SWilly Tarreau return (char *)s; 113930ca2051SWilly Tarreau s++; 114030ca2051SWilly Tarreau } 114130ca2051SWilly Tarreau return NULL; 114230ca2051SWilly Tarreau } 114330ca2051SWilly Tarreau 114430ca2051SWilly Tarreau static __attribute__((unused)) 114530ca2051SWilly Tarreau char *strrchr(const char *s, int c) 114630ca2051SWilly Tarreau { 114730ca2051SWilly Tarreau const char *ret = NULL; 114830ca2051SWilly Tarreau 114930ca2051SWilly Tarreau while (*s) { 115030ca2051SWilly Tarreau if (*s == (char)c) 115130ca2051SWilly Tarreau ret = s; 115230ca2051SWilly Tarreau s++; 115330ca2051SWilly Tarreau } 115430ca2051SWilly Tarreau return (char *)ret; 115530ca2051SWilly Tarreau } 115630ca2051SWilly Tarreau 115730ca2051SWilly Tarreau static __attribute__((unused)) 115830ca2051SWilly Tarreau size_t nolibc_strlen(const char *str) 115930ca2051SWilly Tarreau { 116030ca2051SWilly Tarreau size_t len; 116130ca2051SWilly Tarreau 116230ca2051SWilly Tarreau for (len = 0; str[len]; len++); 116330ca2051SWilly Tarreau return len; 116430ca2051SWilly Tarreau } 116530ca2051SWilly Tarreau 116630ca2051SWilly Tarreau #define strlen(str) ({ \ 116730ca2051SWilly Tarreau __builtin_constant_p((str)) ? \ 116830ca2051SWilly Tarreau __builtin_strlen((str)) : \ 116930ca2051SWilly Tarreau nolibc_strlen((str)); \ 117030ca2051SWilly Tarreau }) 117130ca2051SWilly Tarreau 117230ca2051SWilly Tarreau static __attribute__((unused)) 117330ca2051SWilly Tarreau int isdigit(int c) 117430ca2051SWilly Tarreau { 117530ca2051SWilly Tarreau return (unsigned int)(c - '0') <= 9; 117630ca2051SWilly Tarreau } 117730ca2051SWilly Tarreau 117830ca2051SWilly Tarreau static __attribute__((unused)) 117930ca2051SWilly Tarreau long atol(const char *s) 118030ca2051SWilly Tarreau { 118130ca2051SWilly Tarreau unsigned long ret = 0; 118230ca2051SWilly Tarreau unsigned long d; 118330ca2051SWilly Tarreau int neg = 0; 118430ca2051SWilly Tarreau 118530ca2051SWilly Tarreau if (*s == '-') { 118630ca2051SWilly Tarreau neg = 1; 118730ca2051SWilly Tarreau s++; 118830ca2051SWilly Tarreau } 118930ca2051SWilly Tarreau 119030ca2051SWilly Tarreau while (1) { 119130ca2051SWilly Tarreau d = (*s++) - '0'; 119230ca2051SWilly Tarreau if (d > 9) 119330ca2051SWilly Tarreau break; 119430ca2051SWilly Tarreau ret *= 10; 119530ca2051SWilly Tarreau ret += d; 119630ca2051SWilly Tarreau } 119730ca2051SWilly Tarreau 119830ca2051SWilly Tarreau return neg ? -ret : ret; 119930ca2051SWilly Tarreau } 120030ca2051SWilly Tarreau 120130ca2051SWilly Tarreau static __attribute__((unused)) 120230ca2051SWilly Tarreau int atoi(const char *s) 120330ca2051SWilly Tarreau { 120430ca2051SWilly Tarreau return atol(s); 120530ca2051SWilly Tarreau } 120630ca2051SWilly Tarreau 120730ca2051SWilly Tarreau static __attribute__((unused)) 120830ca2051SWilly Tarreau const char *ltoa(long in) 120930ca2051SWilly Tarreau { 121030ca2051SWilly Tarreau /* large enough for -9223372036854775808 */ 121130ca2051SWilly Tarreau static char buffer[21]; 121230ca2051SWilly Tarreau char *pos = buffer + sizeof(buffer) - 1; 121330ca2051SWilly Tarreau int neg = in < 0; 121430ca2051SWilly Tarreau unsigned long n = neg ? -in : in; 121530ca2051SWilly Tarreau 121630ca2051SWilly Tarreau *pos-- = '\0'; 121730ca2051SWilly Tarreau do { 121830ca2051SWilly Tarreau *pos-- = '0' + n % 10; 121930ca2051SWilly Tarreau n /= 10; 122030ca2051SWilly Tarreau if (pos < buffer) 122130ca2051SWilly Tarreau return pos + 1; 122230ca2051SWilly Tarreau } while (n); 122330ca2051SWilly Tarreau 122430ca2051SWilly Tarreau if (neg) 122530ca2051SWilly Tarreau *pos-- = '-'; 122630ca2051SWilly Tarreau return pos + 1; 122730ca2051SWilly Tarreau } 122830ca2051SWilly Tarreau 122930ca2051SWilly Tarreau __attribute__((weak,unused)) 123030ca2051SWilly Tarreau void *memcpy(void *dst, const void *src, size_t len) 123130ca2051SWilly Tarreau { 123230ca2051SWilly Tarreau return memmove(dst, src, len); 123330ca2051SWilly Tarreau } 123430ca2051SWilly Tarreau 123530ca2051SWilly Tarreau /* needed by libgcc for divide by zero */ 123630ca2051SWilly Tarreau __attribute__((weak,unused)) 123730ca2051SWilly Tarreau int raise(int signal) 123830ca2051SWilly Tarreau { 123930ca2051SWilly Tarreau return kill(getpid(), signal); 124030ca2051SWilly Tarreau } 124130ca2051SWilly Tarreau 124230ca2051SWilly Tarreau /* Here come a few helper functions */ 124330ca2051SWilly Tarreau 124430ca2051SWilly Tarreau static __attribute__((unused)) 124530ca2051SWilly Tarreau void FD_ZERO(fd_set *set) 124630ca2051SWilly Tarreau { 124730ca2051SWilly Tarreau memset(set, 0, sizeof(*set)); 124830ca2051SWilly Tarreau } 124930ca2051SWilly Tarreau 125030ca2051SWilly Tarreau static __attribute__((unused)) 125130ca2051SWilly Tarreau void FD_SET(int fd, fd_set *set) 125230ca2051SWilly Tarreau { 125330ca2051SWilly Tarreau if (fd < 0 || fd >= FD_SETSIZE) 125430ca2051SWilly Tarreau return; 125530ca2051SWilly Tarreau set->fd32[fd / 32] |= 1 << (fd & 31); 125630ca2051SWilly Tarreau } 125730ca2051SWilly Tarreau 125830ca2051SWilly Tarreau /* WARNING, it only deals with the 4096 first majors and 256 first minors */ 125930ca2051SWilly Tarreau static __attribute__((unused)) 126030ca2051SWilly Tarreau dev_t makedev(unsigned int major, unsigned int minor) 126130ca2051SWilly Tarreau { 126230ca2051SWilly Tarreau return ((major & 0xfff) << 8) | (minor & 0xff); 126330ca2051SWilly Tarreau } 1264930c4accSWilly Tarreau 1265930c4accSWilly Tarreau #endif /* _NOLIBC_H */ 1266