diff options
author | Timo Teräs <timo.teras@iki.fi> | 2014-06-07 07:24:12 +0300 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2014-06-07 07:24:12 +0300 |
commit | 838bcec8e10868ef80df1b638d5c8650a7260e7b (patch) | |
tree | 0b9ff8e7eaa7ecc1f05d2b3161b558c01e3c06e4 /main | |
parent | ace7896296b96faa72fcb545501b6efba632f875 (diff) | |
download | aports-838bcec8e10868ef80df1b638d5c8650a7260e7b.tar.bz2 aports-838bcec8e10868ef80df1b638d5c8650a7260e7b.tar.xz |
main/musl: upgrade to 1.1.2
Diffstat (limited to 'main')
-rw-r--r-- | main/musl/0001-v1.1.1-to-76f440cf.patch | 3459 | ||||
-rw-r--r-- | main/musl/0002-76f440cf-to-d85d261e.patch | 89 | ||||
-rw-r--r-- | main/musl/0003-d85d261e-to-2abb70c3.patch | 540 | ||||
-rw-r--r-- | main/musl/1003-implement-y-and-C-specifiers-in-strptime.patch | 64 | ||||
-rw-r--r-- | main/musl/APKBUILD | 26 |
5 files changed, 5 insertions, 4173 deletions
diff --git a/main/musl/0001-v1.1.1-to-76f440cf.patch b/main/musl/0001-v1.1.1-to-76f440cf.patch deleted file mode 100644 index e4025585e..000000000 --- a/main/musl/0001-v1.1.1-to-76f440cf.patch +++ /dev/null @@ -1,3459 +0,0 @@ -diff --git a/arch/arm/bits/syscall.h b/arch/arm/bits/syscall.h -index dc54bde..0b6ea7d 100644 ---- a/arch/arm/bits/syscall.h -+++ b/arch/arm/bits/syscall.h -@@ -333,6 +333,8 @@ - #define __NR_process_vm_writev 377 - #define __NR_kcmp 378 - #define __NR_finit_module 379 -+#define __NR_sched_setattr 380 -+#define __NR_sched_getattr 381 - - - /* Repeated with SYS_ prefix */ -@@ -672,3 +674,5 @@ - #define SYS_process_vm_writev 377 - #define SYS_kcmp 378 - #define SYS_finit_module 379 -+#define SYS_sched_setattr 380 -+#define SYS_sched_getattr 381 -diff --git a/arch/i386/bits/syscall.h b/arch/i386/bits/syscall.h -index 2af242b..7e48791 100644 ---- a/arch/i386/bits/syscall.h -+++ b/arch/i386/bits/syscall.h -@@ -349,6 +349,8 @@ - #define __NR_process_vm_writev 348 - #define __NR_kcmp 349 - #define __NR_finit_module 350 -+#define __NR_sched_setattr 351 -+#define __NR_sched_getattr 352 - - - /* Repeated with SYS_ prefix */ -@@ -704,3 +706,5 @@ - #define SYS_process_vm_writev 348 - #define SYS_kcmp 349 - #define SYS_finit_module 350 -+#define SYS_sched_setattr 351 -+#define SYS_sched_getattr 352 -diff --git a/arch/microblaze/bits/syscall.h b/arch/microblaze/bits/syscall.h -index 712d47a..b8b1d2e 100644 ---- a/arch/microblaze/bits/syscall.h -+++ b/arch/microblaze/bits/syscall.h -@@ -375,6 +375,8 @@ - #define __NR_process_vm_writev 378 - #define __NR_kcmp 379 - #define __NR_finit_module 380 -+#define __NR_sched_setattr 381 -+#define __NR_sched_getattr 382 - - /* Repeated with SYS_ prefix */ - -@@ -756,3 +758,5 @@ - #define SYS_process_vm_writev 378 - #define SYS_kcmp 379 - #define SYS_finit_module 380 -+#define SYS_sched_setattr 381 -+#define SYS_sched_getattr 382 -diff --git a/arch/mips/bits/syscall.h b/arch/mips/bits/syscall.h -index 574d603..f3d30d0 100644 ---- a/arch/mips/bits/syscall.h -+++ b/arch/mips/bits/syscall.h -@@ -346,6 +346,8 @@ - #define __NR_process_vm_writev 4346 - #define __NR_kcmp 4347 - #define __NR_finit_module 4348 -+#define __NR_sched_setattr 4349 -+#define __NR_sched_getattr 4350 - - - /* Repeated with SYS_ prefix */ -@@ -697,3 +699,5 @@ - #define SYS_process_vm_writev 4346 - #define SYS_kcmp 4347 - #define SYS_finit_module 4348 -+#define SYS_sched_setattr 4349 -+#define SYS_sched_getattr 4350 -diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h -index c52976e..e62c339 100644 ---- a/arch/mips/syscall_arch.h -+++ b/arch/mips/syscall_arch.h -@@ -5,6 +5,8 @@ - - long (__syscall)(long, ...); - -+#define SYSCALL_RLIM_INFINITY (-1UL/2) -+ - #ifndef __clang__ - - #define __asm_syscall(...) do { \ -diff --git a/arch/powerpc/bits/syscall.h b/arch/powerpc/bits/syscall.h -index 385860b..16f0abe 100644 ---- a/arch/powerpc/bits/syscall.h -+++ b/arch/powerpc/bits/syscall.h -@@ -368,6 +368,8 @@ - #define __NR_process_vm_writev 352 - #define __NR_finit_module 353 - #define __NR_kcmp 354 -+#define __NR_sched_setattr 355 -+#define __NR_sched_getattr 356 - - /* - * repeated with SYS prefix -@@ -742,3 +744,5 @@ - #define SYS_process_vm_writev 352 - #define SYS_finit_module 353 - #define SYS_kcmp 354 -+#define SYS_sched_setattr 355 -+#define SYS_sched_getattr 356 -diff --git a/arch/x32/bits/syscall.h b/arch/x32/bits/syscall.h -index 95e2d2f..1c245e7 100644 ---- a/arch/x32/bits/syscall.h -+++ b/arch/x32/bits/syscall.h -@@ -271,6 +271,9 @@ - #define __NR_getcpu (__X32_SYSCALL_BIT + 309) - #define __NR_kcmp (__X32_SYSCALL_BIT + 312) - #define __NR_finit_module (__X32_SYSCALL_BIT + 313) -+#define __NR_sched_setattr (__X32_SYSCALL_BIT + 314) -+#define __NR_sched_getattr (__X32_SYSCALL_BIT + 315) -+ - #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512) - #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513) - #define __NR_ioctl (__X32_SYSCALL_BIT + 514) -@@ -591,6 +594,9 @@ - #define SYS_getcpu __NR_getcpu - #define SYS_kcmp __NR_kcmp - #define SYS_finit_module __NR_finit_module -+#define SYS_sched_setattr __NR_sched_setattr -+#define SYS_sched_getattr __NR_sched_getattr -+ - #define SYS_rt_sigaction __NR_rt_sigaction - #define SYS_rt_sigreturn __NR_rt_sigreturn - #define SYS_ioctl __NR_ioctl -diff --git a/arch/x86_64/bits/syscall.h b/arch/x86_64/bits/syscall.h -index 5eb9b83..7bcb711 100644 ---- a/arch/x86_64/bits/syscall.h -+++ b/arch/x86_64/bits/syscall.h -@@ -312,6 +312,8 @@ - #define __NR_process_vm_writev 311 - #define __NR_kcmp 312 - #define __NR_finit_module 313 -+#define __NR_sched_setattr 314 -+#define __NR_sched_getattr 315 - - #undef __NR_fstatat - #undef __NR_pread -@@ -641,6 +643,8 @@ - #define SYS_process_vm_writev 311 - #define SYS_kcmp 312 - #define SYS_finit_module 313 -+#define SYS_sched_setattr 314 -+#define SYS_sched_getattr 315 - - #undef SYS_fstatat - #undef SYS_pread -diff --git a/include/netinet/in.h b/include/netinet/in.h -index ee6e19f..89188c7 100644 ---- a/include/netinet/in.h -+++ b/include/netinet/in.h -@@ -198,6 +198,7 @@ uint16_t ntohs(uint16_t); - #define IP_ORIGDSTADDR 20 - #define IP_RECVORIGDSTADDR IP_ORIGDSTADDR - #define IP_MINTTL 21 -+#define IP_NODEFRAG 22 - #define IP_MULTICAST_IF 32 - #define IP_MULTICAST_TTL 33 - #define IP_MULTICAST_LOOP 34 -@@ -218,6 +219,7 @@ uint16_t ntohs(uint16_t); - #define IP_PMTUDISC_DO 2 - #define IP_PMTUDISC_PROBE 3 - #define IP_PMTUDISC_INTERFACE 4 -+#define IP_PMTUDISC_OMIT 5 - - #define IP_DEFAULT_MULTICAST_TTL 1 - #define IP_DEFAULT_MULTICAST_LOOP 1 -@@ -351,9 +353,17 @@ struct ip6_mtuinfo - #define IPV6_RTHDR 57 - #define IPV6_RECVDSTOPTS 58 - #define IPV6_DSTOPTS 59 -- -+#define IPV6_RECVPATHMTU 60 -+#define IPV6_PATHMTU 61 -+#define IPV6_DONTFRAG 62 - #define IPV6_RECVTCLASS 66 - #define IPV6_TCLASS 67 -+#define IPV6_ADDR_PREFERENCES 72 -+#define IPV6_MINHOPCOUNT 73 -+#define IPV6_ORIGDSTADDR 74 -+#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR -+#define IPV6_TRANSPARENT 75 -+#define IPV6_UNICAST_IF 76 - - #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP - #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP -@@ -364,6 +374,16 @@ struct ip6_mtuinfo - #define IPV6_PMTUDISC_WANT 1 - #define IPV6_PMTUDISC_DO 2 - #define IPV6_PMTUDISC_PROBE 3 -+#define IPV6_PMTUDISC_INTERFACE 4 -+#define IPV6_PMTUDISC_OMIT 5 -+ -+#define IPV6_PREFER_SRC_TMP 0x0001 -+#define IPV6_PREFER_SRC_PUBLIC 0x0002 -+#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100 -+#define IPV6_PREFER_SRC_COA 0x0004 -+#define IPV6_PREFER_SRC_HOME 0x0400 -+#define IPV6_PREFER_SRC_CGA 0x0008 -+#define IPV6_PREFER_SRC_NONCGA 0x0800 - - #define IPV6_RTHDR_LOOSE 0 - #define IPV6_RTHDR_STRICT 1 -diff --git a/include/sched.h b/include/sched.h -index 105dac9..4394b64 100644 ---- a/include/sched.h -+++ b/include/sched.h -@@ -38,6 +38,7 @@ int sched_yield(void); - #define SCHED_RR 2 - #define SCHED_BATCH 3 - #define SCHED_IDLE 5 -+#define SCHED_DEADLINE 6 - #define SCHED_RESET_ON_FORK 0x40000000 - - #ifdef _GNU_SOURCE -diff --git a/include/signal.h b/include/signal.h -index 3fb21b2..c36e4d5 100644 ---- a/include/signal.h -+++ b/include/signal.h -@@ -89,19 +89,24 @@ typedef struct { - union { - char __pad[128 - 2*sizeof(int) - sizeof(long)]; - struct { -- pid_t si_pid; -- uid_t si_uid; -- union sigval si_sigval; -- } __rt; -- struct { -- unsigned int si_timer1, si_timer2; -- } __timer; -- struct { -- pid_t si_pid; -- uid_t si_uid; -- int si_status; -- clock_t si_utime, si_stime; -- } __sigchld; -+ union { -+ struct { -+ pid_t si_pid; -+ uid_t si_uid; -+ } __piduid; -+ struct { -+ int si_timerid; -+ int si_overrun; -+ } __timer; -+ } __first; -+ union { -+ union sigval si_value; -+ struct { -+ int si_status; -+ clock_t si_utime, si_stime; -+ } __sigchld; -+ } __second; -+ } __si_common; - struct { - void *si_addr; - short si_addr_lsb; -@@ -117,20 +122,20 @@ typedef struct { - } __sigsys; - } __si_fields; - } siginfo_t; --#define si_pid __si_fields.__sigchld.si_pid --#define si_uid __si_fields.__sigchld.si_uid --#define si_status __si_fields.__sigchld.si_status --#define si_utime __si_fields.__sigchld.si_utime --#define si_stime __si_fields.__sigchld.si_stime --#define si_value __si_fields.__rt.si_sigval -+#define si_pid __si_fields.__si_common.__first.__piduid.si_pid -+#define si_uid __si_fields.__si_common.__first.__piduid.si_uid -+#define si_status __si_fields.__si_common.__second.__sigchld.si_status -+#define si_utime __si_fields.__si_common.__second.__sigchld.si_utime -+#define si_stime __si_fields.__si_common.__second.__sigchld.si_stime -+#define si_value __si_fields.__si_common.__second.si_value - #define si_addr __si_fields.__sigfault.si_addr - #define si_addr_lsb __si_fields.__sigfault.si_addr_lsb - #define si_band __si_fields.__sigpoll.si_band - #define si_fd __si_fields.__sigpoll.si_fd --#define si_timer1 __si_fields.__timer.si_timer1 --#define si_timer2 __si_fields.__timer.si_timer2 --#define si_ptr __si_fields.__rt.si_sigval.sival_ptr --#define si_int __si_fields.__rt.si_sigval.sival_int -+#define si_timerid __si_fields.__si_common.__first.__timer.si_timerid -+#define si_overrun __si_fields.__si_common.__first.__timer.si_overrun -+#define si_ptr si_value.sival_ptr -+#define si_int si_value.sival_int - #define si_call_addr __si_fields.__sigsys.si_call_addr - #define si_syscall __si_fields.__sigsys.si_syscall - #define si_arch __si_fields.__sigsys.si_arch -diff --git a/include/sys/socket.h b/include/sys/socket.h -index 8e8c9e9..d752791 100644 ---- a/include/sys/socket.h -+++ b/include/sys/socket.h -@@ -203,6 +203,7 @@ struct linger - #define SO_SELECT_ERR_QUEUE 45 - #define SO_BUSY_POLL 46 - #define SO_MAX_PACING_RATE 47 -+#define SO_BPF_EXTENSIONS 48 - - #ifndef SOL_SOCKET - #define SOL_SOCKET 1 -diff --git a/include/sys/types.h b/include/sys/types.h -index 27170f6..f00db03 100644 ---- a/include/sys/types.h -+++ b/include/sys/types.h -@@ -20,11 +20,6 @@ extern "C" { - #define __NEED_timer_t - #define __NEED_clockid_t - --#define __NEED_int8_t --#define __NEED_int16_t --#define __NEED_int32_t --#define __NEED_int64_t -- - #define __NEED_blkcnt_t - #define __NEED_fsblkcnt_t - #define __NEED_fsfilcnt_t -@@ -49,19 +44,22 @@ extern "C" { - #define __NEED_pthread_key_t - #define __NEED_pthread_once_t - #define __NEED_useconds_t --#define __NEED_u_int64_t - - #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -+#define __NEED_int8_t -+#define __NEED_int16_t -+#define __NEED_int32_t -+#define __NEED_int64_t -+#define __NEED_u_int64_t - #define __NEED_register_t - #endif - - #include <bits/alltypes.h> - -+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) - typedef unsigned char u_int8_t; - typedef unsigned short u_int16_t; - typedef unsigned u_int32_t; -- --#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) - typedef char *caddr_t; - typedef unsigned char u_char; - typedef unsigned short u_short, ushort; -@@ -87,5 +85,3 @@ typedef unsigned long long u_quad_t; - } - #endif - #endif -- -- -diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c -index 3498afb..c10a3f3 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,9 +49,13 @@ 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 (__syscall(SYS_open, "/dev/null", O_RDWR|O_LARGEFILE)<0) -+ if (__sys_open("/dev/null", O_RDWR)<0) - a_crash(); - libc.secure = 1; - } -diff --git a/src/exit/exit.c b/src/exit/exit.c -index 353f50b..695bdc0 100644 ---- a/src/exit/exit.c -+++ b/src/exit/exit.c -@@ -1,8 +1,6 @@ - #include <stdlib.h> - #include <stdint.h> - #include "libc.h" --#include "atomic.h" --#include "syscall.h" - - static void dummy() - { -@@ -21,11 +19,6 @@ extern void (*const __fini_array_end)() __attribute__((weak)); - - _Noreturn void exit(int code) - { -- static int lock; -- -- /* If more than one thread calls exit, hang until _Exit ends it all */ -- while (a_swap(&lock, 1)) __syscall(SYS_pause); -- - __funcs_on_exit(); - - #ifndef SHARED -diff --git a/src/exit/quick_exit.c b/src/exit/quick_exit.c -index 1175d80..ada9134 100644 ---- a/src/exit/quick_exit.c -+++ b/src/exit/quick_exit.c -@@ -1,6 +1,4 @@ - #include <stdlib.h> --#include "syscall.h" --#include "atomic.h" - #include "libc.h" - - static void dummy() { } -@@ -8,8 +6,6 @@ weak_alias(dummy, __funcs_on_quick_exit); - - _Noreturn void quick_exit(int code) - { -- static int lock; -- while (a_swap(&lock, 1)) __syscall(SYS_pause); - __funcs_on_quick_exit(); - _Exit(code); - } -diff --git a/src/fcntl/open.c b/src/fcntl/open.c -index be44208..0594ed7 100644 ---- a/src/fcntl/open.c -+++ b/src/fcntl/open.c -@@ -10,7 +10,7 @@ int open(const char *filename, int flags, ...) - va_start(ap, flags); - mode = va_arg(ap, mode_t); - va_end(ap); -- return syscall_cp(SYS_open, filename, flags|O_LARGEFILE, mode); -+ return sys_open_cp(filename, flags, mode); - } - - LFS64(open); -diff --git a/src/internal/syscall.h b/src/internal/syscall.h -index 914b0d1..0a2840a 100644 ---- a/src/internal/syscall.h -+++ b/src/internal/syscall.h -@@ -4,6 +4,10 @@ - #include <sys/syscall.h> - #include "syscall_arch.h" - -+#ifndef SYSCALL_RLIM_INFINITY -+#define SYSCALL_RLIM_INFINITY (~0ULL) -+#endif -+ - #ifndef __scc - #define __scc(X) ((long) (X)) - typedef long syscall_arg_t; -@@ -122,14 +126,26 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), - - #ifdef SYS_stat64 - #undef SYS_stat --#undef SYS_fstat --#undef SYS_lstat --#undef SYS_statfs --#undef SYS_fstatfs - #define SYS_stat SYS_stat64 -+#endif -+ -+#ifdef SYS_fstat64 -+#undef SYS_fstat - #define SYS_fstat SYS_fstat64 -+#endif -+ -+#ifdef SYS_lstat64 -+#undef SYS_lstat - #define SYS_lstat SYS_lstat64 -+#endif -+ -+#ifdef SYS_statfs64 -+#undef SYS_statfs - #define SYS_statfs SYS_statfs64 -+#endif -+ -+#ifdef SYS_fstatfs64 -+#undef SYS_fstatfs - #define SYS_fstatfs SYS_fstatfs64 - #endif - -@@ -163,6 +179,9 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), - #define SYS_fadvise SYS_fadvise64_64 - #endif - -+#ifdef SYS_sendfile64 -+#undef SYS_sendfile -+#define SYS_sendfile SYS_sendfile64 - #endif - - /* socketcall calls */ -@@ -187,3 +206,23 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), - #define __SC_accept4 18 - #define __SC_recvmmsg 19 - #define __SC_sendmmsg 20 -+ -+#ifdef SYS_open -+#define __sys_open2(x,pn,fl) __syscall2(SYS_open, pn, (fl)|O_LARGEFILE) -+#define __sys_open3(x,pn,fl,mo) __syscall3(SYS_open, pn, (fl)|O_LARGEFILE, mo) -+#define __sys_open_cp2(x,pn,fl) __syscall_cp2(SYS_open, pn, (fl)|O_LARGEFILE) -+#define __sys_open_cp3(x,pn,fl,mo) __syscall_cp3(SYS_open, pn, (fl)|O_LARGEFILE, mo) -+#else -+#define __sys_open2(x,pn,fl) __syscall3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE) -+#define __sys_open3(x,pn,fl,mo) __syscall4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) -+#define __sys_open_cp2(x,pn,fl) __syscall_cp3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE) -+#define __sys_open_cp3(x,pn,fl,mo) __syscall_cp4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) -+#endif -+ -+#define __sys_open(...) __SYSCALL_DISP(__sys_open,,__VA_ARGS__) -+#define sys_open(...) __syscall_ret(__sys_open(__VA_ARGS__)) -+ -+#define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__) -+#define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__)) -+ -+#endif -diff --git a/src/linux/epoll.c b/src/linux/epoll.c -index 030786d..deff5b1 100644 ---- a/src/linux/epoll.c -+++ b/src/linux/epoll.c -@@ -1,15 +1,20 @@ - #include <sys/epoll.h> - #include <signal.h> -+#include <errno.h> - #include "syscall.h" - - 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 +24,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 5306648..68e489c 100644 ---- a/src/linux/eventfd.c -+++ b/src/linux/eventfd.c -@@ -1,10 +1,15 @@ - #include <sys/eventfd.h> - #include <unistd.h> -+#include <errno.h> - #include "syscall.h" - - 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 a417c89..df5e48b 100644 ---- a/src/linux/inotify.c -+++ b/src/linux/inotify.c -@@ -1,13 +1,18 @@ - #include <sys/inotify.h> -+#include <errno.h> - #include "syscall.h" - - 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/prlimit.c b/src/linux/prlimit.c -index d1639cc..0fe28e1 100644 ---- a/src/linux/prlimit.c -+++ b/src/linux/prlimit.c -@@ -3,9 +3,24 @@ - #include "syscall.h" - #include "libc.h" - -+#define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0) -+ - int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlimit *old_limit) - { -- return syscall(SYS_prlimit64, pid, resource, new_limit, old_limit); -+ struct rlimit tmp; -+ int r; -+ if (new_limit && SYSCALL_RLIM_INFINITY != RLIM_INFINITY) { -+ tmp = *new_limit; -+ FIX(tmp.rlim_cur); -+ FIX(tmp.rlim_max); -+ new_limit = &tmp; -+ } -+ r = syscall(SYS_prlimit64, pid, resource, new_limit, old_limit); -+ if (!r && old_limit && SYSCALL_RLIM_INFINITY != RLIM_INFINITY) { -+ FIX(old_limit->rlim_cur); -+ FIX(old_limit->rlim_max); -+ } -+ return r; - } - - #undef prlimit64 -diff --git a/src/linux/signalfd.c b/src/linux/signalfd.c -index da6bced..4bf4332 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 70c0695..b814c88 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/misc/getrlimit.c b/src/misc/getrlimit.c -index b7bbd06..b073677 100644 ---- a/src/misc/getrlimit.c -+++ b/src/misc/getrlimit.c -@@ -3,16 +3,24 @@ - #include "syscall.h" - #include "libc.h" - -+#define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0) -+ - int getrlimit(int resource, struct rlimit *rlim) - { - unsigned long k_rlim[2]; - int ret = syscall(SYS_prlimit64, 0, resource, 0, rlim); -+ if (!ret) { -+ FIX(rlim->rlim_cur); -+ FIX(rlim->rlim_max); -+ } - if (!ret || errno != ENOSYS) - return ret; - if (syscall(SYS_getrlimit, resource, k_rlim) < 0) - return -1; - rlim->rlim_cur = k_rlim[0] == -1UL ? RLIM_INFINITY : k_rlim[0]; - rlim->rlim_max = k_rlim[1] == -1UL ? RLIM_INFINITY : k_rlim[1]; -+ FIX(rlim->rlim_cur); -+ FIX(rlim->rlim_max); - return 0; - } - -diff --git a/src/misc/realpath.c b/src/misc/realpath.c -index 4cc7e7d..88c849c 100644 ---- a/src/misc/realpath.c -+++ b/src/misc/realpath.c -@@ -22,7 +22,7 @@ char *realpath(const char *restrict filename, char *restrict resolved) - return 0; - } - -- fd = syscall(SYS_open, filename, O_PATH|O_NONBLOCK|O_CLOEXEC|O_LARGEFILE); -+ fd = sys_open(filename, O_PATH|O_NONBLOCK|O_CLOEXEC); - if (fd < 0) return 0; - __procfdname(buf, fd); - -diff --git a/src/misc/setrlimit.c b/src/misc/setrlimit.c -index ddc13e9..8a1b8cc 100644 ---- a/src/misc/setrlimit.c -+++ b/src/misc/setrlimit.c -@@ -4,14 +4,22 @@ - #include "libc.h" - - #define MIN(a, b) ((a)<(b) ? (a) : (b)) -+#define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0) - - int __setrlimit(int resource, const struct rlimit *rlim) - { - unsigned long k_rlim[2]; -+ struct rlimit tmp; -+ if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) { -+ tmp = *rlim; -+ FIX(tmp.rlim_cur); -+ FIX(tmp.rlim_max); -+ rlim = &tmp; -+ } - int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0); - if (ret != -ENOSYS) return ret; -- k_rlim[0] = MIN(rlim->rlim_cur, -1UL); -- k_rlim[1] = MIN(rlim->rlim_max, -1UL); -+ k_rlim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY)); -+ k_rlim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY)); - return __syscall(SYS_setrlimit, resource, k_rlim); - } - -diff --git a/src/network/__dns.c b/src/network/__dns.c -deleted file mode 100644 -index 97d8031..0000000 ---- a/src/network/__dns.c -+++ /dev/null -@@ -1,282 +0,0 @@ --#include <stdint.h> --#include <netdb.h> --#include <stdio.h> --#include <fcntl.h> --#include <limits.h> --#include <string.h> --#include <sys/socket.h> --#include <poll.h> --#include <netinet/in.h> --#include <time.h> --#include <ctype.h> --#include <unistd.h> --#include <pthread.h> --#include <errno.h> --#include "__dns.h" --#include "stdio_impl.h" -- --#define TIMEOUT 5 --#define RETRY 1000 --#define PACKET_MAX 512 --#define PTR_MAX (64 + sizeof ".in-addr.arpa") -- --static void cleanup(void *p) --{ -- close((intptr_t)p); --} -- --int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) --{ -- time_t t0 = time(0); -- int fd; -- FILE *f, _f; -- unsigned char _buf[256]; -- char line[64], *s, *z; -- union { -- struct sockaddr_in sin; -- struct sockaddr_in6 sin6; -- } sa = {0}, ns[3] = {{0}}; -- socklen_t sl = sizeof sa.sin; -- int nns = 0; -- int family = AF_INET; -- unsigned char q[280] = "", *r = dest; -- int ql; -- int rlen; -- int got = 0, failed = 0; -- int errcode = EAI_AGAIN; -- int i, j; -- struct timespec ts; -- struct pollfd pfd; -- int id; -- int cs; -- -- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); -- -- /* Construct query template - RR and ID will be filled later */ -- if (strlen(name)-1 >= 254U) return EAI_NONAME; -- q[2] = q[5] = 1; -- strcpy((char *)q+13, name); -- for (i=13; q[i]; i=j+1) { -- for (j=i; q[j] && q[j] != '.'; j++); -- if (j-i-1u > 62u) return EAI_NONAME; -- q[i-1] = j-i; -- } -- q[i+3] = 1; -- ql = i+4; -- -- /* Make a reasonably unpredictable id */ -- clock_gettime(CLOCK_REALTIME, &ts); -- id = ts.tv_nsec + ts.tv_nsec/65536UL & 0xffff; -- -- /* Get nameservers from resolv.conf, fallback to localhost */ -- f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf); -- if (f) for (nns=0; nns<3 && fgets(line, sizeof line, f); ) { -- if (strncmp(line, "nameserver", 10) || !isspace(line[10])) -- continue; -- for (s=line+11; isspace(*s); s++); -- for (z=s; *z && !isspace(*z); z++); -- *z=0; -- if (__ipparse(ns+nns, AF_UNSPEC, s) < 0) continue; -- ns[nns].sin.sin_port = htons(53); -- if (ns[nns++].sin.sin_family == AF_INET6) { -- family = AF_INET6; -- sl = sizeof sa.sin6; -- } -- } -- if (f) __fclose_ca(f); -- if (!nns) { -- ns[0].sin.sin_family = family = AF_INET; -- ns[0].sin.sin_port = htons(53); -- ns[0].sin.sin_addr.s_addr = htonl(0x7f000001); -- nns=1; -- sl = sizeof sa.sin; -- } -- -- /* Get local address and open/bind a socket */ -- sa.sin.sin_family = family; -- fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); -- -- /* Handle case where system lacks IPv6 support */ -- if (fd < 0 && errno == EAFNOSUPPORT) { -- if (family != AF_INET6) return EAI_SYSTEM; -- fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); -- family = AF_INET; -- } -- if (fd < 0) return EAI_SYSTEM; -- -- /* Convert any IPv4 addresses in a mixed environment to v4-mapped */ -- if (family == AF_INET6) { -- setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0); -- for (i=0; i<nns; i++) { -- if (ns[i].sin.sin_family != AF_INET) continue; -- memcpy(ns[i].sin6.sin6_addr.s6_addr+12, -- &ns[i].sin.sin_addr, 4); -- memcpy(ns[i].sin6.sin6_addr.s6_addr, -- "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); -- ns[i].sin6.sin6_family = AF_INET6; -- ns[i].sin6.sin6_flowinfo = 0; -- ns[i].sin6.sin6_scope_id = 0; -- } -- } -- -- pthread_cleanup_push(cleanup, (void *)(intptr_t)fd); -- pthread_setcancelstate(cs, 0); -- -- if (bind(fd, (void *)&sa, sl) < 0) { -- errcode = EAI_SYSTEM; -- goto out; -- } -- -- pfd.fd = fd; -- pfd.events = POLLIN; -- -- /* Loop until we timeout; break early on success */ -- for (; time(0)-t0 < TIMEOUT; ) { -- -- /* Query all configured namservers in parallel */ -- for (i=0; i<rrcnt; i++) if (rr[i]) for (j=0; j<nns; j++) { -- q[0] = id+i >> 8; -- q[1] = id+i; -- q[ql-3] = rr[i]; -- sendto(fd, q, ql, MSG_NOSIGNAL, (void *)&ns[j], sl); -- } -- -- /* Wait for a response, or until time to retry */ -- if (poll(&pfd, 1, RETRY) <= 0) continue; -- -- /* Process any and all replies */ -- while (got+failed < rrcnt && (rlen = recvfrom(fd, r, 512, 0, -- (void *)&sa, (socklen_t[1]){sl})) >= 2) -- { -- /* Ignore replies from addresses we didn't send to */ -- for (i=0; i<nns; i++) if (!memcmp(ns+i, &sa, sl)) break; -- if (i==nns) continue; -- -- /* Compute index of the query from id */ -- i = r[0]*256+r[1] - id & 0xffff; -- if ((unsigned)i >= rrcnt || !rr[i]) continue; -- -- /* Interpret the result code */ -- switch (r[3] & 15) { -- case 0: -- got++; -- break; -- case 3: -- if (1) errcode = EAI_NONAME; else -- default: -- errcode = EAI_FAIL; -- failed++; -- } -- -- /* Mark this record as answered */ -- rr[i] = 0; -- r += 512; -- } -- -- /* Check to see if we have answers to all queries */ -- if (got+failed == rrcnt) break; -- } --out: -- pthread_cleanup_pop(1); -- -- /* Return the number of results, or an error code if none */ -- if (got) return got; -- return errcode; --} -- --static void mkptr4(char *s, const unsigned char *ip) --{ -- sprintf(s, "%d.%d.%d.%d.in-addr.arpa", -- ip[3], ip[2], ip[1], ip[0]); --} -- --static void mkptr6(char *s, const unsigned char *ip) --{ -- static const char xdigits[] = "0123456789abcdef"; -- int i; -- for (i=15; i>=0; i--) { -- *s++ = xdigits[ip[i]&15]; *s++ = '.'; -- *s++ = xdigits[ip[i]>>4]; *s++ = '.'; -- } -- strcpy(s, "ip6.arpa"); --} -- --int __dns_query(unsigned char *r, const void *a, int family, int ptr) --{ -- char buf[PTR_MAX]; -- int rr[2], rrcnt = 1; -- -- if (ptr) { -- if (family == AF_INET6) mkptr6(buf, a); -- else mkptr4(buf, a); -- rr[0] = RR_PTR; -- a = buf; -- } else if (family == AF_INET6) { -- rr[0] = RR_AAAA; -- } else { -- rr[0] = RR_A; -- if (family != AF_INET) rr[rrcnt++] = RR_AAAA; -- } -- -- return __dns_doqueries(r, a, rr, rrcnt); --} -- --int __dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); -- --int __dns_get_rr(void *dest, size_t stride, size_t maxlen, size_t limit, const unsigned char *r, int rr, int dec) --{ -- int qdcount, ancount; -- const unsigned char *p; -- char tmp[256]; -- int found = 0; -- int len; -- -- if ((r[3]&15)) return 0; -- p = r+12; -- qdcount = r[4]*256 + r[5]; -- ancount = r[6]*256 + r[7]; -- if (qdcount+ancount > 64) return -1; -- while (qdcount--) { -- while (p-r < 512 && *p-1U < 127) p++; -- if (*p>193 || (*p==193 && p[1]>254) || p>r+506) -- return -1; -- p += 5 + !!*p; -- } -- while (ancount--) { -- while (p-r < 512 && *p-1U < 127) p++; -- if (*p>193 || (*p==193 && p[1]>254) || p>r+506) -- return -1; -- p += 1 + !!*p; -- len = p[8]*256 + p[9]; -- if (p+len > r+512) return -1; -- if (p[1]==rr && len <= maxlen) { -- if (dec && __dn_expand(r, r+512, p+10, tmp, sizeof tmp)<0) -- return -1; -- if (dest && limit) { -- if (dec) strcpy(dest, tmp); -- else memcpy(dest, p+10, len); -- dest = (char *)dest + stride; -- limit--; -- } -- found++; -- } -- p += 10 + len; -- } -- return found; --} -- --int __dns_count_addrs(const unsigned char *r, int cnt) --{ -- int found=0, res, i; -- static const int p[2][2] = { { 4, RR_A }, { 16, RR_AAAA } }; -- -- while (cnt--) { -- for (i=0; i<2; i++) { -- res = __dns_get_rr(0, 0, p[i][0], -1, r, p[i][1], 0); -- if (res < 0) return res; -- found += res; -- } -- r += 512; -- } -- return found; --} -diff --git a/src/network/__dns.h b/src/network/__dns.h -deleted file mode 100644 -index 9a3f740..0000000 ---- a/src/network/__dns.h -+++ /dev/null -@@ -1,14 +0,0 @@ --#include <stddef.h> -- --#define RR_A 1 --#define RR_CNAME 5 --#define RR_PTR 12 --#define RR_AAAA 28 -- --int __dns_count_addrs(const unsigned char *, int); --int __dns_get_rr(void *, size_t, size_t, size_t, const unsigned char *, int, int); -- --int __dns_query(unsigned char *, const void *, int, int); --int __ipparse(void *, int, const char *); -- --int __dns_doqueries(unsigned char *, const char *, int *, int); -diff --git a/src/network/__ipparse.c b/src/network/__ipparse.c -deleted file mode 100644 -index 79f3b8c..0000000 ---- a/src/network/__ipparse.c -+++ /dev/null -@@ -1,51 +0,0 @@ --#include <stdlib.h> --#include <ctype.h> --#include <sys/socket.h> --#include <netinet/in.h> --#include <arpa/inet.h> --#include "__dns.h" -- --int __ipparse(void *dest, int family, const char *s0) --{ -- const char *s = s0; -- unsigned char *d = dest; -- unsigned long a[16] = { 0 }; -- char *z; -- int i; -- -- if (family == AF_INET6) goto not_v4; -- -- for (i=0; i<4; i++) { -- a[i] = strtoul(s, &z, 0); -- if (z==s || (*z && *z != '.') || !isdigit(*s)) { -- if (family == AF_INET) return -1; -- goto not_v4; -- } -- if (!*z) break; -- s=z+1; -- } -- if (i==4) return -1; -- switch (i) { -- case 0: -- a[1] = a[0] & 0xffffff; -- a[0] >>= 24; -- case 1: -- a[2] = a[1] & 0xffff; -- a[1] >>= 16; -- case 2: -- a[3] = a[2] & 0xff; -- a[2] >>= 8; -- } -- ((struct sockaddr_in *)d)->sin_family = AF_INET; -- d = (void *)&((struct sockaddr_in *)d)->sin_addr; -- for (i=0; i<4; i++) { -- if (a[i] > 255) return -1; -- d[i] = a[i]; -- } -- return 0; -- --not_v4: -- s = s0; -- ((struct sockaddr_in6 *)d)->sin6_family = AF_INET6; -- return inet_pton(AF_INET6, s, (void *)&((struct sockaddr_in6 *)d)->sin6_addr) <= 0 ? -1 : 0; --} -diff --git a/src/network/dns_parse.c b/src/network/dns_parse.c -new file mode 100644 -index 0000000..aa0d39f ---- /dev/null -+++ b/src/network/dns_parse.c -@@ -0,0 +1,31 @@ -+#include <string.h> -+ -+int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, const void *, int, const void *), void *ctx) -+{ -+ int qdcount, ancount; -+ const unsigned char *p; -+ int len; -+ -+ if ((r[3]&15)) return 0; -+ p = r+12; -+ qdcount = r[4]*256 + r[5]; -+ ancount = r[6]*256 + r[7]; -+ if (qdcount+ancount > 64) return -1; -+ while (qdcount--) { -+ while (p-r < rlen && *p-1U < 127) p++; -+ if (*p>193 || (*p==193 && p[1]>254) || p>r+506) -+ return -1; -+ p += 5 + !!*p; -+ } -+ while (ancount--) { -+ while (p-r < rlen && *p-1U < 127) p++; -+ if (*p>193 || (*p==193 && p[1]>254) || p>r+506) -+ return -1; -+ p += 1 + !!*p; -+ len = p[8]*256 + p[9]; -+ if (p+len > r+rlen) return -1; -+ if (callback(ctx, p[1], p+10, len, r) < 0) return -1; -+ p += 10 + len; -+ } -+ return 0; -+} -diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c -index 5d45be7..70b6cfd 100644 ---- a/src/network/getaddrinfo.c -+++ b/src/network/getaddrinfo.c -@@ -1,249 +1,115 @@ - #include <stdlib.h> --#include <stdio.h> --#include <netdb.h> --#include <netinet/in.h> - #include <sys/socket.h> --#include <unistd.h> -+#include <netinet/in.h> -+#include <netdb.h> - #include <string.h> --#include <ctype.h> --#include "__dns.h" --#include "stdio_impl.h" -- --static int is_valid(const char *host) --{ -- const unsigned char *s; -- if (strlen(host)-1 > 254 || mbstowcs(0, host, 0) > 255) return 0; -- for (s=(void *)host; *s>=0x80 || *s=='.' || *s=='-' || isalnum(*s); s++); -- return !*s; --} -- --#if 0 --static int have_af(int family) --{ -- struct sockaddr_in6 sin6 = { .sin6_family = family }; -- socklen_t sl = family == AF_INET -- ? sizeof(struct sockaddr_in) -- : sizeof(struct sockaddr_in6); -- int sock = socket(family, SOCK_STREAM, 0); -- int have = !bind(sock, (void *)&sin6, sl); -- close(sock); -- return have; --} --#endif -- --union sa { -- struct sockaddr_in sin; -- struct sockaddr_in6 sin6; --}; -- --struct aibuf { -- struct addrinfo ai; -- union sa sa; --}; -- --/* Extra slots needed for storing canonical name */ --#define EXTRA ((256+sizeof(struct aibuf)-1)/sizeof(struct aibuf)) -+#include "lookup.h" - - int getaddrinfo(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict hint, struct addrinfo **restrict res) - { -- int flags = hint ? hint->ai_flags : 0; -- int family = hint ? hint->ai_family : AF_UNSPEC; -- int type = hint ? hint->ai_socktype : 0; -- int proto = hint ? hint->ai_protocol : 0; -- unsigned long port = 0; -- struct aibuf *buf; -- union sa sa = {{0}}; -- unsigned char reply[1024]; -- int i, j; -- char line[512]; -- FILE *f, _f; -- unsigned char _buf[1024]; -- char *z; -- int result; -- int cnt; -- -- if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC) -- return EAI_FAMILY; -- -- if (host && strlen(host)>255) return EAI_NONAME; -- if (serv && strlen(serv)>32) return EAI_SERVICE; -- -- if (type && !proto) -- proto = type==SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP; -- if (!type && proto) -- type = proto==IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; -- -- if (serv) { -- if (!*serv) return EAI_SERVICE; -- port = strtoul(serv, &z, 10); -- if (*z) { -- size_t servlen = strlen(serv); -- char *end = line; -- -- if (flags & AI_NUMERICSERV) return EAI_SERVICE; -+ struct service ports[MAXSERVS]; -+ struct address addrs[MAXADDRS]; -+ char canon[256], *outcanon; -+ int nservs, naddrs, nais, canon_len, i, j, k; -+ int family = AF_UNSPEC, flags = 0, proto = 0; -+ struct aibuf { -+ struct addrinfo ai; -+ union sa { -+ struct sockaddr_in sin; -+ struct sockaddr_in6 sin6; -+ } sa; -+ } *out; -+ -+ if (hint) { -+ family = hint->ai_family; -+ flags = hint->ai_flags; -+ proto = hint->ai_protocol; -+ -+ const int mask = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | -+ AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG | AI_NUMERICSERV; -+ if ((flags & mask) != flags) -+ return EAI_BADFLAGS; -+ -+ switch (family) { -+ case AF_INET: -+ case AF_INET6: -+ case AF_UNSPEC: -+ break; -+ default: -+ return EAI_FAMILY; -+ } - -- f = __fopen_rb_ca("/etc/services", &_f, _buf, sizeof _buf); -- if (!f) return EAI_SERVICE; -- while (fgets(line, sizeof line, f)) { -- if (strncmp(line, serv, servlen) || !isspace(line[servlen])) -- continue; -- port = strtoul(line+servlen, &end, 10); -- if (strncmp(end, proto==IPPROTO_UDP ? "/udp" : "/tcp", 4)) -- continue; -+ switch (hint->ai_socktype) { -+ case SOCK_STREAM: -+ switch (proto) { -+ case 0: -+ proto = IPPROTO_TCP; -+ case IPPROTO_TCP: - break; -+ default: -+ return EAI_SERVICE; - } -- __fclose_ca(f); -- if (feof(f)) return EAI_SERVICE; -- } -- if (port > 65535) return EAI_SERVICE; -- port = htons(port); -- } -- -- if (!host) { -- if (family == AF_UNSPEC) { -- cnt = 2; family = AF_INET; -- } else { -- cnt = 1; -- } -- buf = calloc(sizeof *buf, cnt); -- if (!buf) return EAI_MEMORY; -- for (i=0; i<cnt; i++) { -- if (i) family = AF_INET6; -- buf[i].ai.ai_protocol = proto; -- buf[i].ai.ai_socktype = type; -- buf[i].ai.ai_addr = (void *)&buf[i].sa; -- buf[i].ai.ai_addrlen = family==AF_INET6 -- ? sizeof sa.sin6 : sizeof sa.sin; -- buf[i].ai.ai_family = family; -- buf[i].sa.sin.sin_family = family; -- buf[i].sa.sin.sin_port = port; -- if (i+1<cnt) buf[i].ai.ai_next = &buf[i+1].ai; -- if (!(flags & AI_PASSIVE)) { -- if (family == AF_INET) { -- 0[(uint8_t*)&buf[i].sa.sin.sin_addr.s_addr]=127; -- 3[(uint8_t*)&buf[i].sa.sin.sin_addr.s_addr]=1; -- } else buf[i].sa.sin6.sin6_addr.s6_addr[15] = 1; -+ break; -+ case SOCK_DGRAM: -+ switch (proto) { -+ case 0: -+ proto = IPPROTO_UDP; -+ case IPPROTO_UDP: -+ break; -+ default: -+ return EAI_SERVICE; - } -+ case 0: -+ break; -+ default: -+ return EAI_SOCKTYPE; - } -- *res = &buf->ai; -- return 0; -- } -- -- if (!*host) return EAI_NONAME; -- -- /* Try as a numeric address */ -- if (__ipparse(&sa, family, host) >= 0) { -- buf = calloc(sizeof *buf, 1+EXTRA); -- if (!buf) return EAI_MEMORY; -- family = sa.sin.sin_family; -- buf->ai.ai_protocol = proto; -- buf->ai.ai_socktype = type; -- buf->ai.ai_addr = (void *)&buf->sa; -- buf->ai.ai_addrlen = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin; -- buf->ai.ai_family = family; -- buf->ai.ai_canonname = (char *)host; -- buf->sa = sa; -- buf->sa.sin.sin_port = port; -- *res = &buf->ai; -- return 0; - } - -- if (flags & AI_NUMERICHOST) return EAI_NONAME; -+ nservs = __lookup_serv(ports, serv, proto, flags); -+ if (nservs < 0) return nservs; - -- f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf); -- if (f) while (fgets(line, sizeof line, f)) { -- char *p; -- size_t l = strlen(host); -+ naddrs = __lookup_name(addrs, canon, host, family, flags); -+ if (naddrs < 0) return naddrs; - -- if ((p=strchr(line, '#'))) *p++='\n', *p=0; -- for(p=line+1; (p=strstr(p, host)) && -- (!isspace(p[-1]) || !isspace(p[l])); p++); -- if (!p) continue; -- __fclose_ca(f); -- -- /* Isolate IP address to parse */ -- for (p=line; *p && !isspace(*p); p++); -- *p++ = 0; -- if (__ipparse(&sa, family, line) < 0) return EAI_NONAME; -- -- /* Allocate and fill result buffer */ -- buf = calloc(sizeof *buf, 1+EXTRA); -- if (!buf) return EAI_MEMORY; -- family = sa.sin.sin_family; -- buf->ai.ai_protocol = proto; -- buf->ai.ai_socktype = type; -- buf->ai.ai_addr = (void *)&buf->sa; -- buf->ai.ai_addrlen = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin; -- buf->ai.ai_family = family; -- buf->sa = sa; -- buf->sa.sin.sin_port = port; -- -- /* Extract first name as canonical name */ -- for (; *p && isspace(*p); p++); -- buf->ai.ai_canonname = (void *)(buf+1); -- snprintf(buf->ai.ai_canonname, 256, "%s", p); -- for (p=buf->ai.ai_canonname; *p && !isspace(*p); p++); -- *p = 0; -- if (!is_valid(buf->ai.ai_canonname)) -- buf->ai.ai_canonname = 0; -- -- *res = &buf->ai; -- return 0; -- } -- if (f) __fclose_ca(f); -+ nais = nservs * naddrs; -+ canon_len = strlen(canon); -+ out = calloc(1, nais * sizeof(*out) + canon_len + 1); -+ if (!out) return EAI_MEMORY; - --#if 0 -- f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf); -- if (f) while (fgets(line, sizeof line, f)) { -- if (!isspace(line[10]) || (strncmp(line, "search", 6) -- && strncmp(line, "domain", 6))) continue; -+ if (canon_len) { -+ outcanon = (void *)&out[nais]; -+ memcpy(outcanon, canon, canon_len+1); -+ } else { -+ outcanon = 0; - } -- if (f) __fclose_ca(f); --#endif - -- /* Perform one or more DNS queries for host */ -- memset(reply, 0, sizeof reply); -- result = __dns_query(reply, host, family, 0); -- if (result < 0) return result; -- -- cnt = __dns_count_addrs(reply, result); -- if (cnt <= 0) return EAI_NONAME; -- -- buf = calloc(sizeof *buf, cnt+EXTRA); -- if (!buf) return EAI_MEMORY; -- -- i = 0; -- if (family != AF_INET6) { -- j = __dns_get_rr(&buf[i].sa.sin.sin_addr, sizeof *buf, 4, cnt-i, reply, RR_A, 0); -- while (j--) buf[i++].sa.sin.sin_family = AF_INET; -- } -- if (family != AF_INET) { -- j = __dns_get_rr(&buf[i].sa.sin6.sin6_addr, sizeof *buf, 16, cnt-i, reply, RR_AAAA, 0); -- while (j--) buf[i++].sa.sin.sin_family = AF_INET6; -- } -- if (result>1) { -- j = __dns_get_rr(&buf[i].sa.sin.sin_addr, sizeof *buf, 4, cnt-i, reply+512, RR_A, 0); -- while (j--) buf[i++].sa.sin.sin_family = AF_INET; -- j = __dns_get_rr(&buf[i].sa.sin6.sin6_addr, sizeof *buf, 16, cnt-i, reply+512, RR_AAAA, 0); -- while (j--) buf[i++].sa.sin.sin_family = AF_INET6; -- } -- -- if (__dns_get_rr((void *)&buf[cnt], 0, 256, 1, reply, RR_CNAME, 1) <= 0) -- strcpy((void *)&buf[cnt], host); -- -- for (i=0; i<cnt; i++) { -- buf[i].ai.ai_protocol = proto; -- buf[i].ai.ai_socktype = type; -- buf[i].ai.ai_addr = (void *)&buf[i].sa; -- buf[i].ai.ai_addrlen = buf[i].sa.sin.sin_family==AF_INET6 -- ? sizeof sa.sin6 : sizeof sa.sin; -- buf[i].ai.ai_family = buf[i].sa.sin.sin_family; -- buf[i].sa.sin.sin_port = port; -- buf[i].ai.ai_next = &buf[i+1].ai; -- buf[i].ai.ai_canonname = (void *)&buf[cnt]; -+ for (k=i=0; i<naddrs; i++) for (j=0; j<nservs; j++, k++) { -+ out[k].ai = (struct addrinfo){ -+ .ai_family = addrs[i].family, -+ .ai_socktype = ports[j].proto == IPPROTO_TCP -+ ? SOCK_STREAM : SOCK_DGRAM, -+ .ai_protocol = ports[j].proto, -+ .ai_addrlen = addrs[i].family == AF_INET -+ ? sizeof(struct sockaddr_in) -+ : sizeof(struct sockaddr_in6), -+ .ai_addr = (void *)&out[k].sa, -+ .ai_canonname = outcanon, -+ .ai_next = &out[k+1].ai }; -+ switch (addrs[i].family) { -+ case AF_INET: -+ out[k].sa.sin.sin_family = AF_INET; -+ out[k].sa.sin.sin_port = htons(ports[j].port); -+ memcpy(&out[k].sa.sin.sin_addr, &addrs[i].addr, 4); -+ break; -+ case AF_INET6: -+ out[k].sa.sin6.sin6_family = AF_INET6; -+ out[k].sa.sin6.sin6_port = htons(ports[j].port); -+ memcpy(&out[k].sa.sin6.sin6_addr, &addrs[i].addr, 16); -+ break; -+ } - } -- buf[cnt-1].ai.ai_next = 0; -- *res = &buf->ai; -- -+ out[nais-1].ai.ai_next = 0; -+ *res = &out->ai; - return 0; - } -diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c -index 27eb080..aa8b0a9 100644 ---- a/src/network/gethostbyname2_r.c -+++ b/src/network/gethostbyname2_r.c -@@ -6,41 +6,31 @@ - #include <netinet/in.h> - #include <errno.h> - #include <stdint.h> -+#include "lookup.h" - - int gethostbyname2_r(const char *name, int af, - struct hostent *h, char *buf, size_t buflen, - struct hostent **res, int *err) - { -- struct addrinfo hint = { -- .ai_family = af==AF_INET6 ? af : AF_INET, -- .ai_flags = AI_CANONNAME -- }; -- struct addrinfo *ai, *p; -- int i; -- size_t need; -- const char *canon; -+ struct address addrs[MAXADDRS]; -+ char canon[256]; -+ int i, cnt; -+ size_t align, need; - -- af = hint.ai_family; -- -- /* Align buffer */ -- i = (uintptr_t)buf & sizeof(char *)-1; -- if (i) { -- if (buflen < sizeof(char *)-i) return ERANGE; -- buf += sizeof(char *)-i; -- buflen -= sizeof(char *)-i; -- } -- -- switch (getaddrinfo(name, 0, &hint, &ai)) { -+ cnt = __lookup_name(addrs, canon, name, af, AI_CANONNAME); -+ if (cnt<0) switch (cnt) { - case EAI_NONAME: - *err = HOST_NOT_FOUND; -- return errno; -+ return ENOENT; - case EAI_AGAIN: - *err = TRY_AGAIN; -- return errno; -+ return EAGAIN; - default: -+ case EAI_FAIL: -+ *err = NO_RECOVERY; -+ return EBADMSG; - case EAI_MEMORY: - case EAI_SYSTEM: -- case EAI_FAIL: - *err = NO_RECOVERY; - return errno; - case 0: -@@ -50,22 +40,22 @@ int gethostbyname2_r(const char *name, int af, - h->h_addrtype = af; - h->h_length = af==AF_INET6 ? 16 : 4; - -- canon = ai->ai_canonname ? ai->ai_canonname : name; -+ /* Align buffer */ -+ align = -(uintptr_t)buf & sizeof(char *)-1; -+ - need = 4*sizeof(char *); -- for (i=0, p=ai; p; i++, p=p->ai_next) -- need += sizeof(char *) + h->h_length; -+ need += (cnt + 1) * (sizeof(char *) + h->h_length); - need += strlen(name)+1; - need += strlen(canon)+1; -+ need += align; - -- if (need > buflen) { -- freeaddrinfo(ai); -- return ERANGE; -- } -+ if (need > buflen) return ERANGE; - -+ buf += align; - h->h_aliases = (void *)buf; - buf += 3*sizeof(char *); - h->h_addr_list = (void *)buf; -- buf += (i+1)*sizeof(char *); -+ buf += (cnt+1)*sizeof(char *); - - h->h_name = h->h_aliases[0] = buf; - strcpy(h->h_name, canon); -@@ -79,16 +69,13 @@ int gethostbyname2_r(const char *name, int af, - - h->h_aliases[2] = 0; - -- for (i=0, p=ai; p; i++, p=p->ai_next) { -+ for (i=0; i<cnt; i++) { - h->h_addr_list[i] = (void *)buf; - buf += h->h_length; -- memcpy(h->h_addr_list[i], -- &((struct sockaddr_in *)p->ai_addr)->sin_addr, -- h->h_length); -+ memcpy(h->h_addr_list[i], addrs[i].addr, h->h_length); - } - h->h_addr_list[i] = 0; - - *res = h; -- freeaddrinfo(ai); - return 0; - } -diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c -index 33f89a3..dfcf6ed 100644 ---- a/src/network/getnameinfo.c -+++ b/src/network/getnameinfo.c -@@ -5,15 +5,50 @@ - #include <sys/socket.h> - #include <netinet/in.h> - #include <arpa/inet.h> --#include "__dns.h" -+ -+int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *), void *); -+int __dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); -+int __res_mkquery(int, const char *, int, int, const unsigned char *, int, const unsigned char*, unsigned char *, int); -+int __res_send(const unsigned char *, int, unsigned char *, int); -+ -+#define PTR_MAX (64 + sizeof ".in-addr.arpa") -+#define RR_PTR 12 -+ -+static void mkptr4(char *s, const unsigned char *ip) -+{ -+ sprintf(s, "%d.%d.%d.%d.in-addr.arpa", -+ ip[3], ip[2], ip[1], ip[0]); -+} -+ -+static void mkptr6(char *s, const unsigned char *ip) -+{ -+ static const char xdigits[] = "0123456789abcdef"; -+ int i; -+ for (i=15; i>=0; i--) { -+ *s++ = xdigits[ip[i]&15]; *s++ = '.'; -+ *s++ = xdigits[ip[i]>>4]; *s++ = '.'; -+ } -+ strcpy(s, "ip6.arpa"); -+} -+ -+static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet) -+{ -+ char tmp[256]; -+ if (rr != RR_PTR) return 0; -+ if (__dn_expand(packet, (const unsigned char *)packet + 512, -+ data, tmp, sizeof tmp) > 0) -+ strcpy(c, tmp); -+ return 0; -+ -+} - - int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, - char *restrict node, socklen_t nodelen, - char *restrict serv, socklen_t servlen, - int flags) - { -+ char ptr[PTR_MAX]; - char buf[256]; -- unsigned char reply[512]; - int af = sa->sa_family; - unsigned char *a; - -@@ -21,20 +56,32 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, - case AF_INET: - a = (void *)&((struct sockaddr_in *)sa)->sin_addr; - if (sl != sizeof(struct sockaddr_in)) return EAI_FAMILY; -+ mkptr4(ptr, a); - break; - case AF_INET6: - a = (void *)&((struct sockaddr_in6 *)sa)->sin6_addr; - if (sl != sizeof(struct sockaddr_in6)) return EAI_FAMILY; -+ if (memcmp(a, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12)) -+ mkptr6(ptr, a); -+ else -+ mkptr4(ptr, a+12); - break; - default: - return EAI_FAMILY; - } - - if (node && nodelen) { -- if ((flags & NI_NUMERICHOST) -- || __dns_query(reply, a, af, 1) <= 0 -- || __dns_get_rr(buf, 0, 256, 1, reply, RR_PTR, 1) <= 0) -- { -+ buf[0] = 0; -+ if (!(flags & NI_NUMERICHOST)) { -+ unsigned char query[18+PTR_MAX], reply[512]; -+ int qlen = __res_mkquery(0, ptr, 1, RR_PTR, -+ 0, 0, 0, query, sizeof query); -+ int rlen = __res_send(query, qlen, reply, sizeof reply); -+ buf[0] = 0; -+ if (rlen > 0) -+ __dns_parse(reply, rlen, dns_parse_callback, buf); -+ } -+ if (!*buf) { - if (flags & NI_NAMEREQD) return EAI_NONAME; - inet_ntop(af, a, buf, sizeof buf); - } -diff --git a/src/network/getservbyname.c b/src/network/getservbyname.c -index 0b00ce1..dd30376 100644 ---- a/src/network/getservbyname.c -+++ b/src/network/getservbyname.c -@@ -4,7 +4,7 @@ - struct servent *getservbyname(const char *name, const char *prots) - { - static struct servent se; -- static long buf[32/sizeof(long)]; -+ static char *buf[2]; - struct servent *res; - if (getservbyname_r(name, prots, &se, (void *)buf, sizeof buf, &res)) - return 0; -diff --git a/src/network/getservbyname_r.c b/src/network/getservbyname_r.c -index 811c174..8cdf622 100644 ---- a/src/network/getservbyname_r.c -+++ b/src/network/getservbyname_r.c -@@ -5,49 +5,43 @@ - #include <inttypes.h> - #include <errno.h> - #include <string.h> -+#include "lookup.h" -+ -+#define ALIGN (sizeof(struct { char a; char *b; }) - sizeof(char *)) - - int getservbyname_r(const char *name, const char *prots, - struct servent *se, char *buf, size_t buflen, struct servent **res) - { -- struct addrinfo *ai, hint = { .ai_family = AF_INET }; -- int i; -- -- if (!prots) { -- int r = getservbyname_r(name, "tcp", se, buf, buflen, res); -- if (r) r = getservbyname_r(name, "udp", se, buf, buflen, res); -- return r; -- } -+ struct service servs[MAXSERVS]; -+ int cnt, proto, align; - - /* Align buffer */ -- i = (uintptr_t)buf & sizeof(char *)-1; -- if (!i) i = sizeof(char *); -- if (buflen < 3*sizeof(char *)-i) -+ align = -(uintptr_t)buf & ALIGN-1; -+ if (buflen < 2*sizeof(char *)+align) - return ERANGE; -- buf += sizeof(char *)-i; -- buflen -= sizeof(char *)-i; -+ buf += align; - -- if (!strcmp(prots, "tcp")) hint.ai_protocol = IPPROTO_TCP; -- else if (!strcmp(prots, "udp")) hint.ai_protocol = IPPROTO_UDP; -+ if (!prots) proto = 0; -+ else if (!strcmp(prots, "tcp")) proto = IPPROTO_TCP; -+ else if (!strcmp(prots, "udp")) proto = IPPROTO_UDP; - else return EINVAL; - -- switch (getaddrinfo(0, name, &hint, &ai)) { -+ cnt = __lookup_serv(servs, name, proto, 0); -+ if (cnt<0) switch (cnt) { - case EAI_MEMORY: - case EAI_SYSTEM: - return ENOMEM; - default: - return ENOENT; -- case 0: -- break; - } - - se->s_name = (char *)name; - se->s_aliases = (void *)buf; - se->s_aliases[0] = se->s_name; - se->s_aliases[1] = 0; -- se->s_port = ((struct sockaddr_in *)ai->ai_addr)->sin_port; -- se->s_proto = (char *)prots; -+ se->s_port = htons(servs[0].port); -+ se->s_proto = servs[0].proto == IPPROTO_TCP ? "tcp" : "udp"; - -- freeaddrinfo(ai); - *res = se; - return 0; - } -diff --git a/src/network/inet_addr.c b/src/network/inet_addr.c -index ea0a8f7..10b21f2 100644 ---- a/src/network/inet_addr.c -+++ b/src/network/inet_addr.c -@@ -1,11 +1,12 @@ - #include <sys/socket.h> - #include <netinet/in.h> - #include <arpa/inet.h> --#include "__dns.h" -+ -+int __inet_aton(const char *, struct in_addr *); - - in_addr_t inet_addr(const char *p) - { -- struct sockaddr_in sin; -- if (__ipparse(&sin, AF_INET, p) < 0) return -1; -- return sin.sin_addr.s_addr; -+ struct in_addr a; -+ if (!__inet_aton(p, &a)) return -1; -+ return a.s_addr; - } -diff --git a/src/network/inet_aton.c b/src/network/inet_aton.c -new file mode 100644 -index 0000000..0f9a45f ---- /dev/null -+++ b/src/network/inet_aton.c -@@ -0,0 +1,41 @@ -+#include <ctype.h> -+#include <sys/socket.h> -+#include <netinet/in.h> -+#include <arpa/inet.h> -+#include "libc.h" -+ -+int __inet_aton(const char *s0, struct in_addr *dest) -+{ -+ const char *s = s0; -+ unsigned char *d = (void *)dest; -+ unsigned long a[4] = { 0 }; -+ char *z; -+ int i; -+ -+ for (i=0; i<4; i++) { -+ a[i] = strtoul(s, &z, 0); -+ if (z==s || (*z && *z != '.') || !isdigit(*s)) -+ return 0; -+ if (!*z) break; -+ s=z+1; -+ } -+ if (i==4) return 0; -+ switch (i) { -+ case 0: -+ a[1] = a[0] & 0xffffff; -+ a[0] >>= 24; -+ case 1: -+ a[2] = a[1] & 0xffff; -+ a[1] >>= 16; -+ case 2: -+ a[3] = a[2] & 0xff; -+ a[2] >>= 8; -+ } -+ for (i=0; i<4; i++) { -+ if (a[i] > 255) return 0; -+ d[i] = a[i]; -+ } -+ return 1; -+} -+ -+weak_alias(__inet_aton, inet_aton); -diff --git a/src/network/inet_legacy.c b/src/network/inet_legacy.c -index de5b75c..621b47b 100644 ---- a/src/network/inet_legacy.c -+++ b/src/network/inet_legacy.c -@@ -1,21 +1,12 @@ - #include <sys/socket.h> - #include <netinet/in.h> - #include <arpa/inet.h> --#include "__dns.h" - - in_addr_t inet_network(const char *p) - { - return ntohl(inet_addr(p)); - } - --int inet_aton(const char *cp, struct in_addr *inp) --{ -- struct sockaddr_in sin; -- if (__ipparse(&sin, AF_INET, cp) < 0) return 0; -- *inp = sin.sin_addr; -- return 1; --} -- - struct in_addr inet_makeaddr(in_addr_t n, in_addr_t h) - { - if (n < 256) h |= n<<24; -diff --git a/src/network/lookup.h b/src/network/lookup.h -new file mode 100644 -index 0000000..82c969e ---- /dev/null -+++ b/src/network/lookup.h -@@ -0,0 +1,26 @@ -+#ifndef LOOKUP_H -+#define LOOKUP_H -+ -+#include <stdint.h> -+ -+struct address { -+ int family; -+ unsigned scopeid; -+ uint8_t addr[16]; -+}; -+ -+struct service { -+ uint16_t port; -+ char proto; -+}; -+ -+/* The limit of 48 results is a non-sharp bound on the number of addresses -+ * that can fit in one 512-byte DNS packet full of v4 results and a second -+ * packet full of v6 results. Due to headers, the actual limit is lower. */ -+#define MAXADDRS 48 -+#define MAXSERVS 2 -+ -+int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int flags); -+int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags); -+ -+#endif -diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c -new file mode 100644 -index 0000000..8d41627 ---- /dev/null -+++ b/src/network/lookup_name.c -@@ -0,0 +1,210 @@ -+#include <sys/socket.h> -+#include <netinet/in.h> -+#include <netdb.h> -+#include <arpa/inet.h> -+#include <ctype.h> -+#include <stdlib.h> -+#include <string.h> -+#include <fcntl.h> -+#include "lookup.h" -+#include "stdio_impl.h" -+#include "syscall.h" -+ -+static int is_valid_hostname(const char *host) -+{ -+ const unsigned char *s; -+ if (strnlen(host, 256)-1 > 254 || mbstowcs(0, host, 0) > 255) return 0; -+ for (s=(void *)host; *s>=0x80 || *s=='.' || *s=='-' || isalnum(*s); s++); -+ return !*s; -+} -+ -+static int name_from_null(struct address buf[static 2], const char *name, int family, int flags) -+{ -+ int cnt = 0; -+ if (name) return 0; -+ if (flags & AI_PASSIVE) { -+ if (family != AF_INET6) -+ buf[cnt++] = (struct address){ .family = AF_INET }; -+ if (family != AF_INET) -+ buf[cnt++] = (struct address){ .family = AF_INET6 }; -+ } else { -+ if (family != AF_INET6) -+ buf[cnt++] = (struct address){ .family = AF_INET, .addr = { 127,0,0,1 } }; -+ if (family != AF_INET) -+ buf[cnt++] = (struct address){ .family = AF_INET6, .addr = { [15] = 1 } }; -+ } -+ return cnt; -+} -+ -+int __inet_aton(const char *, struct in_addr *); -+ -+static int name_from_numeric(struct address buf[static 1], const char *name, int family) -+{ -+ struct in_addr a4; -+ struct in6_addr a6; -+ if (family != AF_INET6 && __inet_aton(name, &a4)>0) { -+ memcpy(&buf[0].addr, &a4, sizeof a4); -+ buf[0].family = AF_INET; -+ return 1; -+ } -+ if (family != AF_INET && inet_pton(AF_INET6, name, &a6)>0) { -+ memcpy(&buf[0].addr, &a6, sizeof a6); -+ buf[0].family = AF_INET6; -+ return 1; -+ } -+ return 0; -+} -+ -+static int name_from_hosts(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) -+{ -+ char line[512]; -+ size_t l = strlen(name); -+ int cnt = 0; -+ unsigned char _buf[1032]; -+ FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf); -+ if (!f) return 0; -+ while (fgets(line, sizeof line, f) && cnt < MAXADDRS) { -+ char *p, *z; -+ -+ if ((p=strchr(line, '#'))) *p++='\n', *p=0; -+ for(p=line+1; (p=strstr(p, name)) && -+ (!isspace(p[-1]) || !isspace(p[l])); p++); -+ if (!p) continue; -+ -+ /* Isolate IP address to parse */ -+ for (p=line; *p && !isspace(*p); p++); -+ *p++ = 0; -+ if (name_from_numeric(buf+cnt, line, family)) -+ cnt++; -+ -+ /* Extract first name as canonical name */ -+ for (; *p && isspace(*p); p++); -+ for (z=p; *z && !isspace(*z); z++); -+ *z = 0; -+ if (is_valid_hostname(p)) memcpy(canon, p, z-p+1); -+ } -+ __fclose_ca(f); -+ return cnt; -+} -+ -+struct dpc_ctx { -+ struct address *addrs; -+ char *canon; -+ int cnt; -+}; -+ -+int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *), void *); -+int __dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); -+int __res_mkquery(int, const char *, int, int, const unsigned char *, int, const unsigned char*, unsigned char *, int); -+int __res_msend(int, const unsigned char *const *, const int *, unsigned char *const *, int *, int); -+ -+#define RR_A 1 -+#define RR_CNAME 5 -+#define RR_AAAA 28 -+ -+static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet) -+{ -+ char tmp[256]; -+ struct dpc_ctx *ctx = c; -+ switch (rr) { -+ case RR_A: -+ if (len != 4) return -1; -+ ctx->addrs[ctx->cnt].family = AF_INET; -+ memcpy(ctx->addrs[ctx->cnt++].addr, data, 4); -+ break; -+ case RR_AAAA: -+ if (len != 16) return -1; -+ ctx->addrs[ctx->cnt].family = AF_INET6; -+ memcpy(ctx->addrs[ctx->cnt++].addr, data, 16); -+ break; -+ case RR_CNAME: -+ if (__dn_expand(packet, (const unsigned char *)packet + 512, -+ data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp)) -+ strcpy(ctx->canon, tmp); -+ break; -+ } -+ return 0; -+} -+ -+static int name_from_dns(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) -+{ -+ unsigned char qbuf[2][280], abuf[2][512]; -+ const unsigned char *qp[2] = { qbuf[0], qbuf[1] }; -+ unsigned char *ap[2] = { abuf[0], abuf[1] }; -+ int qlens[2], alens[2]; -+ int i, nq = 0; -+ struct dpc_ctx ctx = { .addrs = buf, .canon = canon }; -+ -+ if (family != AF_INET6) { -+ qlens[nq] = __res_mkquery(0, name, 1, RR_A, 0, 0, 0, -+ qbuf[nq], sizeof *qbuf); -+ nq++; -+ } -+ if (family != AF_INET) { -+ qlens[nq] = __res_mkquery(0, name, 1, RR_AAAA, 0, 0, 0, -+ qbuf[nq], sizeof *qbuf); -+ nq++; -+ } -+ -+ if (__res_msend(nq, qp, qlens, ap, alens, sizeof *abuf) < 0) return EAI_SYSTEM; -+ -+ for (i=0; i<nq; i++) -+ __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); -+ -+ return ctx.cnt; -+} -+ -+int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags) -+{ -+ int cnt = 0, i, j; -+ -+ *canon = 0; -+ if (name) { -+ size_t l; -+ if ((l = strnlen(name, 256))-1 > 254) -+ return EAI_NONAME; -+ memcpy(canon, name, l+1); -+ } -+ -+ /* Procedurally, a request for v6 addresses with the v4-mapped -+ * flag set is like a request for unspecified family, followed -+ * by filtering of the results. */ -+ if (flags & AI_V4MAPPED) { -+ if (family == AF_INET6) family = AF_UNSPEC; -+ else flags -= AI_V4MAPPED; -+ } -+ -+ /* Try each backend until there's at least one result. */ -+ cnt = name_from_null(buf, name, family, flags); -+ if (cnt<=0) cnt = name_from_numeric(buf, name, family); -+ if (cnt<=0 && !(flags & AI_NUMERICHOST)) { -+ cnt = name_from_hosts(buf, canon, name, family); -+ if (cnt<=0) cnt = name_from_dns(buf, canon, name, family); -+ } -+ if (cnt<=0) return cnt ? cnt : EAI_NONAME; -+ -+ /* Filter/transform results for v4-mapped lookup, if requested. */ -+ if (flags & AI_V4MAPPED) { -+ if (!(flags & AI_ALL)) { -+ /* If any v6 results exist, remove v4 results. */ -+ for (i=0; i<cnt && buf[i].family != AF_INET6; i++); -+ if (i<cnt) { -+ for (j=0; i<cnt; i++) { -+ if (buf[i].family == AF_INET6) -+ buf[j++] = buf[i]; -+ } -+ cnt = i = j; -+ } -+ } -+ /* Translate any remaining v4 results to v6 */ -+ for (i=0; i<cnt; i++) { -+ if (buf[i].family != AF_INET) continue; -+ memcpy(buf[i].addr+12, buf[i].addr, 4); -+ memcpy(buf[i].addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); -+ buf[i].scopeid = 0; -+ buf[i].family = AF_INET6; -+ } -+ } -+ -+ return cnt; -+} -diff --git a/src/network/lookup_serv.c b/src/network/lookup_serv.c -new file mode 100644 -index 0000000..bf4cba0 ---- /dev/null -+++ b/src/network/lookup_serv.c -@@ -0,0 +1,72 @@ -+#include <sys/socket.h> -+#include <netinet/in.h> -+#include <netdb.h> -+#include <ctype.h> -+#include <string.h> -+#include <fcntl.h> -+#include "lookup.h" -+#include "stdio_impl.h" -+ -+int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int flags) -+{ -+ char line[128]; -+ int cnt = 0; -+ char *p, *z = ""; -+ unsigned long port = 0; -+ -+ if (name) { -+ if (!*name) return EAI_SERVICE; -+ port = strtoul(name, &z, 10); -+ } -+ if (!*z) { -+ if (port > 65535) return EAI_SERVICE; -+ if (proto != IPPROTO_UDP) { -+ buf[cnt].port = port; -+ buf[cnt++].proto = IPPROTO_TCP; -+ } -+ if (proto != IPPROTO_TCP) { -+ buf[cnt].port = port; -+ buf[cnt++].proto = IPPROTO_UDP; -+ } -+ return cnt; -+ } -+ -+ if (flags & AI_NUMERICSERV) return EAI_SERVICE; -+ -+ size_t l = strlen(name); -+ -+ unsigned char _buf[1032]; -+ FILE _f, *f = __fopen_rb_ca("/etc/services", &_f, _buf, sizeof _buf); -+ if (!f) return EAI_SERVICE; -+ -+ while (fgets(line, sizeof line, f) && cnt < MAXSERVS) { -+ if ((p=strchr(line, '#'))) *p++='\n', *p=0; -+ -+ /* Find service name */ -+ for(p=line; (p=strstr(p, name)); p++) { -+ if (p>line && !isspace(p[-1])) continue; -+ if (p[l] && !isspace(p[l])) continue; -+ break; -+ } -+ if (!p) continue; -+ -+ /* Skip past canonical name at beginning of line */ -+ for (p=line; *p && !isspace(*p); p++); -+ if (!p) continue; -+ -+ port = strtoul(p, &z, 10); -+ if (port > 65535 || z==p) continue; -+ if (!strncmp(z, "/udp", 4)) { -+ if (proto == IPPROTO_TCP) continue; -+ buf[cnt].port = port; -+ buf[cnt++].proto = IPPROTO_UDP; -+ } -+ if (!strncmp(z, "/tcp", 4)) { -+ if (proto == IPPROTO_UDP) continue; -+ buf[cnt].port = port; -+ buf[cnt++].proto = IPPROTO_TCP; -+ } -+ } -+ __fclose_ca(f); -+ return cnt > 0 ? cnt : EAI_SERVICE; -+} -diff --git a/src/network/proto.c b/src/network/proto.c -index 3d0f584..1b51e15 100644 ---- a/src/network/proto.c -+++ b/src/network/proto.c -@@ -14,7 +14,11 @@ static const unsigned char protos[][8] = { - "\021udp", - "\026idp", - "\051ipv6", -+ "\057gre", -+ "\062esp", -+ "\063ah", - "\072icmpv6", -+ "\136ipip", - "\377raw", - "\0\0" - }; -diff --git a/src/network/res_init.c b/src/network/res_init.c -index cbd5b15..5dba9df 100644 ---- a/src/network/res_init.c -+++ b/src/network/res_init.c -@@ -1,3 +1,5 @@ -+#include <resolv.h> -+ - int res_init() - { - return 0; -diff --git a/src/network/res_mkquery.c b/src/network/res_mkquery.c -new file mode 100644 -index 0000000..f7e4e9c ---- /dev/null -+++ b/src/network/res_mkquery.c -@@ -0,0 +1,41 @@ -+#include <resolv.h> -+#include <string.h> -+#include <time.h> -+#include "libc.h" -+ -+int __res_mkquery(int op, const char *dname, int class, int type, -+ const unsigned char *data, int datalen, -+ const unsigned char *newrr, unsigned char *buf, int buflen) -+{ -+ int id, i, j; -+ unsigned char q[280]; -+ struct timespec ts; -+ size_t l = strnlen(dname, 256); -+ -+ if (l-1>=254 || buflen<18+l || op>15u || class>255u || type>255u) -+ return -1; -+ -+ /* Construct query template - ID will be filled later */ -+ memset(q, 0, 18+l); -+ q[2] = op*8 + 1; -+ q[5] = 1; -+ memcpy((char *)q+13, dname, l); -+ for (i=13; q[i]; i=j+1) { -+ for (j=i; q[j] && q[j] != '.'; j++); -+ if (j-i-1u > 62u) return -1; -+ q[i-1] = j-i; -+ } -+ q[i+1] = type; -+ q[i+3] = class; -+ -+ /* Make a reasonably unpredictable id */ -+ clock_gettime(CLOCK_REALTIME, &ts); -+ id = ts.tv_nsec + ts.tv_nsec/65536UL & 0xffff; -+ q[0] = id/256; -+ q[1] = id; -+ -+ memcpy(buf, q, 18+l); -+ return 18+l; -+} -+ -+weak_alias(__res_mkquery, res_mkquery); -diff --git a/src/network/res_msend.c b/src/network/res_msend.c -new file mode 100644 -index 0000000..a5b7793 ---- /dev/null -+++ b/src/network/res_msend.c -@@ -0,0 +1,185 @@ -+#include <sys/socket.h> -+#include <netinet/in.h> -+#include <netdb.h> -+#include <arpa/inet.h> -+#include <stdint.h> -+#include <string.h> -+#include <poll.h> -+#include <time.h> -+#include <ctype.h> -+#include <unistd.h> -+#include <errno.h> -+#include <pthread.h> -+#include "stdio_impl.h" -+#include "syscall.h" -+ -+static void cleanup(void *p) -+{ -+ __syscall(SYS_close, (intptr_t)p); -+} -+ -+static unsigned long mtime() -+{ -+ struct timespec ts; -+ clock_gettime(CLOCK_REALTIME, &ts); -+ return (unsigned long)ts.tv_sec * 1000 -+ + ts.tv_nsec / 1000000; -+} -+ -+int __res_msend(int nqueries, const unsigned char *const *queries, -+ const int *qlens, unsigned char *const *answers, int *alens, int asize) -+{ -+ int fd; -+ FILE *f, _f; -+ unsigned char _buf[256]; -+ char line[64], *s, *z; -+ int timeout = 5000, attempts = 2, retry_interval; -+ union { -+ struct sockaddr_in sin; -+ struct sockaddr_in6 sin6; -+ } sa = {0}, ns[3] = {{0}}; -+ socklen_t sl = sizeof sa.sin; -+ int nns = 0; -+ int family = AF_INET; -+ int rlen; -+ int next; -+ int i, j; -+ int cs; -+ struct pollfd pfd; -+ unsigned long t0, t1, t2; -+ -+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); -+ -+ /* Get nameservers from resolv.conf, fallback to localhost */ -+ f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf); -+ if (f) for (nns=0; nns<3 && fgets(line, sizeof line, f); ) { -+ if (!strncmp(line, "options", 7) && isspace(line[7])) { -+ unsigned long x; -+ char *p, *z; -+ p = strstr(line, "timeout:"); -+ if (p && isdigit(p[8])) { -+ p += 8; -+ x = strtoul(p, &z, 10); -+ if (z != p) timeout = x < 30 ? x*1000 : 30000; -+ } -+ p = strstr(line, "attempts:"); -+ if (p && isdigit(p[9])) { -+ p += 9; -+ x = strtoul(p, &z, 10); -+ if (z != p) attempts = x < 10 ? x : 10; -+ if (!attempts) attempts = 1; -+ } -+ } -+ if (strncmp(line, "nameserver", 10) || !isspace(line[10])) -+ continue; -+ for (s=line+11; isspace(*s); s++); -+ for (z=s; *z && !isspace(*z); z++); -+ *z=0; -+ -+ if (inet_pton(AF_INET, s, &ns[nns].sin.sin_addr)>0) { -+ ns[nns].sin.sin_port = htons(53); -+ ns[nns++].sin.sin_family = AF_INET; -+ } else if (inet_pton(AF_INET6, s, &ns[nns].sin6.sin6_addr)>0) { -+ sl = sizeof sa.sin6; -+ ns[nns].sin6.sin6_port = htons(53); -+ ns[nns++].sin6.sin6_family = family = AF_INET6; -+ } -+ } -+ if (f) __fclose_ca(f); -+ if (!nns) { -+ ns[0].sin.sin_family = AF_INET; -+ ns[0].sin.sin_port = htons(53); -+ ns[0].sin.sin_addr.s_addr = htonl(0x7f000001); -+ nns=1; -+ } -+ -+ /* Get local address and open/bind a socket */ -+ sa.sin.sin_family = family; -+ fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); -+ -+ /* Handle case where system lacks IPv6 support */ -+ if (fd < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) { -+ fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); -+ family = AF_INET; -+ } -+ if (fd < 0 || bind(fd, (void *)&sa, sl) < 0) return -1; -+ -+ /* Past this point, there are no errors. Each individual query will -+ * yield either no reply (indicated by zero length) or an answer -+ * packet which is up to the caller to interpret. */ -+ -+ pthread_cleanup_push(cleanup, (void *)(intptr_t)fd); -+ pthread_setcancelstate(cs, 0); -+ -+ /* Convert any IPv4 addresses in a mixed environment to v4-mapped */ -+ if (family == AF_INET6) { -+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0); -+ for (i=0; i<nns; i++) { -+ if (ns[i].sin.sin_family != AF_INET) continue; -+ memcpy(ns[i].sin6.sin6_addr.s6_addr+12, -+ &ns[i].sin.sin_addr, 4); -+ memcpy(ns[i].sin6.sin6_addr.s6_addr, -+ "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); -+ ns[i].sin6.sin6_family = AF_INET6; -+ ns[i].sin6.sin6_flowinfo = 0; -+ ns[i].sin6.sin6_scope_id = 0; -+ } -+ } -+ -+ memset(alens, 0, sizeof *alens * nqueries); -+ -+ pfd.fd = fd; -+ pfd.events = POLLIN; -+ retry_interval = timeout / attempts; -+ next = 0; -+ t0 = t2 = mtime(); -+ t1 = t2 - retry_interval; -+ -+ for (; t2-t0 < timeout; t2=mtime()) { -+ if (t2-t1 >= retry_interval) { -+ /* Query all configured namservers in parallel */ -+ for (i=0; i<nqueries; i++) -+ if (!alens[i]) -+ for (j=0; j<nns; j++) -+ sendto(fd, queries[i], -+ qlens[i], MSG_NOSIGNAL, -+ (void *)&ns[j], sl); -+ t1 = t2; -+ } -+ -+ /* Wait for a response, or until time to retry */ -+ if (poll(&pfd, 1, t1+retry_interval-t2) <= 0) continue; -+ -+ while ((rlen = recvfrom(fd, answers[next], asize, 0, -+ (void *)&sa, (socklen_t[1]){sl})) >= 0) { -+ -+ /* Ignore non-identifiable packets (no query id) */ -+ if (rlen < 2) continue; -+ -+ /* Ignore replies from addresses we didn't send to */ -+ for (i=0; i<nns && memcmp(ns+i, &sa, sl); i++); -+ if (i==nns) continue; -+ -+ /* Find which query this answer goes with, if any */ -+ for (i=next; i<nqueries && ( -+ answers[next][0] != queries[i][0] || -+ answers[next][1] != queries[i][1] ); i++); -+ if (i==nqueries) continue; -+ if (alens[i]) continue; -+ -+ /* Store answer in the right slot, or update next -+ * available temp slot if it's already in place. */ -+ alens[i] = rlen; -+ if (i == next) -+ for (; next<nqueries && alens[next]; next++); -+ else -+ memcpy(answers[i], answers[next], rlen); -+ -+ if (next == nqueries) goto out; -+ } -+ } -+out: -+ pthread_cleanup_pop(1); -+ -+ return 0; -+} -diff --git a/src/network/res_query.c b/src/network/res_query.c -index 3847da3..2b4e4bb 100644 ---- a/src/network/res_query.c -+++ b/src/network/res_query.c -@@ -1,25 +1,17 @@ --#define _GNU_SOURCE - #include <resolv.h> - #include <netdb.h> --#include "__dns.h" - #include "libc.h" - --int res_query(const char *name, int class, int type, unsigned char *dest, int len) -+int __res_mkquery(int, const char *, int, int, const unsigned char *, int, const unsigned char*, unsigned char *, int); -+int __res_send(const unsigned char *, int, unsigned char *, int); -+ -+int __res_query(const char *name, int class, int type, unsigned char *dest, int len) - { -- if (class != 1 || len < 512) -- return -1; -- switch(__dns_doqueries(dest, name, &type, 1)) { -- case EAI_NONAME: -- h_errno = HOST_NOT_FOUND; -- return -1; -- case EAI_AGAIN: -- h_errno = TRY_AGAIN; -- return -1; -- case EAI_FAIL: -- h_errno = NO_RECOVERY; -- return -1; -- } -- return 512; -+ unsigned char q[280]; -+ int ql = __res_mkquery(0, name, class, type, 0, 0, 0, q, sizeof q); -+ if (ql < 0) return ql; -+ return __res_send(q, ql, dest, len); - } - --weak_alias(res_query, res_search); -+weak_alias(__res_query, res_query); -+weak_alias(__res_query, res_search); -diff --git a/src/network/res_querydomain.c b/src/network/res_querydomain.c -new file mode 100644 -index 0000000..c746dbe ---- /dev/null -+++ b/src/network/res_querydomain.c -@@ -0,0 +1,14 @@ -+#include <resolv.h> -+#include <string.h> -+ -+int res_querydomain(const char *name, const char *domain, int class, int type, unsigned char *dest, int len) -+{ -+ char tmp[256]; -+ size_t nl = strnlen(name, 256); -+ size_t dl = strnlen(domain, 256); -+ if (nl+dl+1 > 255) return -1; -+ memcpy(tmp, name, nl); -+ tmp[nl] = '.'; -+ memcpy(tmp+nl+1, domain, dl+1); -+ return res_query(tmp, class, type, dest, len); -+} -diff --git a/src/network/res_send.c b/src/network/res_send.c -new file mode 100644 -index 0000000..19cfe0f ---- /dev/null -+++ b/src/network/res_send.c -@@ -0,0 +1,12 @@ -+#include <resolv.h> -+#include "libc.h" -+ -+int __res_msend(int, const unsigned char *const *, const int *, unsigned char *const *, int *, int); -+ -+int __res_send(const unsigned char *msg, int msglen, unsigned char *answer, int anslen) -+{ -+ int r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen); -+ return r<0 ? r : anslen; -+} -+ -+weak_alias(__res_send, res_send); -diff --git a/src/process/fork.c b/src/process/fork.c -index 864c7d7..f8cf21e 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 f675a13..08928b0 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,15 +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 = __syscall(SYS_open, op->path, -- op->oflag | O_LARGEFILE, op->mode); -+ 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/process/vfork.c b/src/process/vfork.c -index fc4adb4..ac95465 100644 ---- a/src/process/vfork.c -+++ b/src/process/vfork.c -@@ -1,12 +1,17 @@ - #define _GNU_SOURCE - #include <unistd.h> -+#include <signal.h> - #include "syscall.h" - #include "libc.h" - - pid_t __vfork(void) - { - /* vfork syscall cannot be made from C code */ -+#ifdef SYS_fork - return syscall(SYS_fork); -+#else -+ return syscall(SYS_clone, SIGCHLD, 0); -+#endif - } - - weak_alias(__vfork, vfork); -diff --git a/src/select/poll.c b/src/select/poll.c -index f1e73e8..9e0bcbd 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/pselect.c b/src/select/pselect.c -index a19e153..4e2d7b0 100644 ---- a/src/select/pselect.c -+++ b/src/select/pselect.c -@@ -1,11 +1,12 @@ - #include <sys/select.h> - #include <signal.h> -+#include <stdint.h> - #include "syscall.h" - #include "libc.h" - - int pselect(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, const struct timespec *restrict ts, const sigset_t *restrict mask) - { -- long data[2] = { (long)mask, _NSIG/8 }; -+ syscall_arg_t data[2] = { (uintptr_t)mask, _NSIG/8 }; - struct timespec ts_tmp; - if (ts) ts_tmp = *ts; - return syscall_cp(SYS_pselect6, n, rfds, wfds, efds, ts ? &ts_tmp : 0, data); -diff --git a/src/select/select.c b/src/select/select.c -index f93597b..7b5f6dc 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 beb66e5..d4f53c5 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 6d28141..93e1b64 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 12e7ff0..afa6d44 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/fstat.c b/src/stat/fstat.c -index b561176..a928986 100644 ---- a/src/stat/fstat.c -+++ b/src/stat/fstat.c -@@ -14,7 +14,11 @@ int fstat(int fd, struct stat *st) - - 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); -+#endif - } - - LFS64(fstat); -diff --git a/src/stat/futimesat.c b/src/stat/futimesat.c -index dbefc84..b4eea1d 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 8f60358..5e8b84f 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 770e1cc..32625b7 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 c319657..beebd84 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 c6de716..b4433a0 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 929698b..159c8be 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/__fopen_rb_ca.c b/src/stdio/__fopen_rb_ca.c -index 9202c8c..b72c630 100644 ---- a/src/stdio/__fopen_rb_ca.c -+++ b/src/stdio/__fopen_rb_ca.c -@@ -6,7 +6,7 @@ FILE *__fopen_rb_ca(const char *filename, FILE *f, unsigned char *buf, size_t le - { - memset(f, 0, sizeof *f); - -- f->fd = syscall(SYS_open, filename, O_RDONLY|O_LARGEFILE|O_CLOEXEC, 0); -+ f->fd = sys_open(filename, O_RDONLY|O_CLOEXEC); - if (f->fd < 0) return 0; - - f->flags = F_NOWR | F_PERM; -diff --git a/src/stdio/fopen.c b/src/stdio/fopen.c -index da17ce8..3d97cfa 100644 ---- a/src/stdio/fopen.c -+++ b/src/stdio/fopen.c -@@ -18,7 +18,7 @@ FILE *fopen(const char *restrict filename, const char *restrict mode) - /* Compute the flags to pass to open() */ - flags = __fmodeflags(mode); - -- fd = syscall_cp(SYS_open, filename, flags|O_LARGEFILE, 0666); -+ fd = sys_open_cp(filename, flags, 0666); - if (fd < 0) return 0; - - f = __fdopen(fd, mode); -diff --git a/src/stdio/remove.c b/src/stdio/remove.c -index e147ba2..942e301 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 97f1453..04c90c0 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 f73ca9f..45a5f26 100644 ---- a/src/stdio/tempnam.c -+++ b/src/stdio/tempnam.c -@@ -1,42 +1,48 @@ - #include <stdio.h> -+#include <fcntl.h> -+#include <errno.h> -+#include <sys/stat.h> -+#include <limits.h> - #include <string.h> --#include <stdlib.h> --#include <stdint.h> --#include <unistd.h> --#include <time.h> --#include "libc.h" --#include "atomic.h" -+#include "syscall.h" - - #define MAXTRIES 100 - -+char *__randname(char *); -+ - char *tempnam(const char *dir, const char *pfx) - { -- static int index; -- char *s; -- struct timespec ts; -- int pid = getpid(); -- size_t l; -- int n; -- int try=0; -+ char s[PATH_MAX]; -+ size_t l, dl, pl; -+ int try; -+ int r; - - if (!dir) dir = P_tmpdir; - if (!pfx) pfx = "temp"; - -- if (access(dir, R_OK|W_OK|X_OK) != 0) -- return NULL; -- -- l = strlen(dir) + 1 + strlen(pfx) + 3*(sizeof(int)*3+2) + 1; -- s = malloc(l); -- if (!s) return s; -+ dl = strlen(dir); -+ pl = strlen(pfx); -+ l = dl + 1 + pl + 1 + 6; - -- do { -- clock_gettime(CLOCK_REALTIME, &ts); -- n = ts.tv_nsec ^ (uintptr_t)&s ^ (uintptr_t)s; -- snprintf(s, l, "%s/%s-%d-%d-%x", dir, pfx, pid, a_fetch_add(&index, 1), n); -- } while (!access(s, F_OK) && try++<MAXTRIES); -- if (try>=MAXTRIES) { -- free(s); -+ if (l >= PATH_MAX) { -+ errno = ENAMETOOLONG; - return 0; - } -- return s; -+ -+ memcpy(s, dir, dl); -+ s[dl] = '/'; -+ memcpy(s+dl+1, pfx, pl); -+ s[dl+1+pl] = '_'; -+ -+ 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 926d660..a7d0000 100644 ---- a/src/stdio/tmpfile.c -+++ b/src/stdio/tmpfile.c -@@ -1,23 +1,27 @@ - #include <stdio.h> - #include <fcntl.h> --#include <unistd.h> - #include "stdio_impl.h" - - #define MAXTRIES 100 - -+char *__randname(char *); -+ - FILE *tmpfile(void) - { -- char buf[L_tmpnam], *s; -+ char s[] = "/tmp/tmpfile_XXXXXX"; - int fd; - FILE *f; - int try; - for (try=0; try<MAXTRIES; try++) { -- s = tmpnam(buf); -- if (!s) return 0; -- fd = syscall(SYS_open, s, O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600); -+ __randname(s+13); -+ 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 2bd72b3..449eb9b 100644 ---- a/src/stdio/tmpnam.c -+++ b/src/stdio/tmpnam.c -@@ -1,31 +1,29 @@ - #include <stdio.h> --#include <stdlib.h> --#include <stdint.h> --#include <unistd.h> --#include <time.h> --#include "libc.h" -+#include <fcntl.h> -+#include <errno.h> -+#include <sys/stat.h> -+#include <string.h> - #include "syscall.h" --#include "atomic.h" - - #define MAXTRIES 100 - --char *tmpnam(char *s) --{ -- static int index; -- static char s2[L_tmpnam]; -- struct timespec ts; -- int try = 0; -- unsigned n; -- -- if (!s) s = s2; -+char *__randname(char *); - -- if (__syscall(SYS_access, P_tmpdir, R_OK|W_OK|X_OK) != 0) -- return NULL; -- -- do { -- __syscall(SYS_clock_gettime, CLOCK_REALTIME, &ts, 0); -- n = ts.tv_nsec ^ (uintptr_t)&s ^ (uintptr_t)s; -- snprintf(s, L_tmpnam, "/tmp/t%x-%x", a_fetch_add(&index, 1), n); -- } while (!__syscall(SYS_access, s, F_OK) && try++<MAXTRIES); -- return try>=MAXTRIES ? 0 : s; -+char *tmpnam(char *buf) -+{ -+ static char internal[L_tmpnam]; -+ char s[] = "/tmp/tmpnam_XXXXXX"; -+ int try; -+ 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/stdio/vfprintf.c b/src/stdio/vfprintf.c -index f6e7f38..ea25772 100644 ---- a/src/stdio/vfprintf.c -+++ b/src/stdio/vfprintf.c -@@ -13,8 +13,6 @@ - - #define MAX(a,b) ((a)>(b) ? (a) : (b)) - #define MIN(a,b) ((a)<(b) ? (a) : (b)) --#define CONCAT2(x,y) x ## y --#define CONCAT(x,y) CONCAT2(x,y) - - /* Convenient bit representation for modifier flags, which all fall - * within 31 codepoints of the space character. */ -@@ -343,7 +341,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) - x = *d % i; - /* Are there any significant digits past j? */ - if (x || d+1!=z) { -- long double round = CONCAT(0x1p,LDBL_MANT_DIG); -+ long double round = 2/LDBL_EPSILON; - long double small; - if (*d/i & 1) round += 2; - if (x<i/2) small=0x0.8p0; -diff --git a/src/time/__map_file.c b/src/time/__map_file.c -index 84ae839..d06a581 100644 ---- a/src/time/__map_file.c -+++ b/src/time/__map_file.c -@@ -9,8 +9,7 @@ const char unsigned *__map_file(const char *pathname, size_t *size) - { - struct stat st; - const unsigned char *map = MAP_FAILED; -- int flags = O_RDONLY|O_LARGEFILE|O_CLOEXEC|O_NONBLOCK; -- int fd = __syscall(SYS_open, pathname, flags); -+ int fd = __sys_open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK); - if (fd < 0) return 0; - if (!__syscall(SYS_fstat, fd, &st)) - map = __mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); -diff --git a/src/time/utime.c b/src/time/utime.c -index b2b5741..e7592b2 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 e7ce73a..d6eed68 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 95f6f61..14b0325 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 87a0d44..8f43c6d 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 1f7134b..0eb6caf 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 36633b0..0345984 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 433f42e..90e9bb0 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 de871ae..ccd5ee0 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 20193f2..feec18e 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 f7ed17d..56eb171 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 36c6f13..d07b8d2 100644 ---- a/src/unistd/pipe.c -+++ b/src/unistd/pipe.c -@@ -3,5 +3,9 @@ - - int pipe(int fd[2]) - { -+#ifdef SYS_pipe - return syscall(SYS_pipe, fd); -+#else -+ return syscall(SYS_pipe2, fd, 0); -+#endif - } -diff --git a/src/unistd/readlink.c b/src/unistd/readlink.c -index ec291e3..a152d52 100644 ---- a/src/unistd/readlink.c -+++ b/src/unistd/readlink.c -@@ -1,7 +1,12 @@ - #include <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 dfe1605..6825ffc 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 5902d45..0973d78 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 bdb37be..c40c28d 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 - } diff --git a/main/musl/0002-76f440cf-to-d85d261e.patch b/main/musl/0002-76f440cf-to-d85d261e.patch deleted file mode 100644 index 67e2e46ed..000000000 --- a/main/musl/0002-76f440cf-to-d85d261e.patch +++ /dev/null @@ -1,89 +0,0 @@ -diff --git a/src/multibyte/wcsrtombs.c b/src/multibyte/wcsrtombs.c -index 5cf8f3e..30be415 100644 ---- a/src/multibyte/wcsrtombs.c -+++ b/src/multibyte/wcsrtombs.c -@@ -21,8 +21,13 @@ size_t wcsrtombs(char *restrict s, const wchar_t **restrict ws, size_t n, mbstat - } - return n; - } -- while (n>=4 && **ws) { -- if (**ws >= 0x80u) { -+ while (n>=4) { -+ if (**ws-1u >= 0x7fu) { -+ if (!**ws) { -+ *s = 0; -+ *ws = 0; -+ return N-n; -+ } - l = wcrtomb(s, **ws, 0); - if (!(l+1)) return -1; - s += l; -@@ -33,8 +38,13 @@ size_t wcsrtombs(char *restrict s, const wchar_t **restrict ws, size_t n, mbstat - } - (*ws)++; - } -- while (n && **ws) { -- if (**ws >= 0x80u) { -+ while (n) { -+ if (**ws-1u >= 0x7fu) { -+ if (!**ws) { -+ *s = 0; -+ *ws = 0; -+ return N-n; -+ } - l = wcrtomb(buf, **ws, 0); - if (!(l+1)) return -1; - if (l>n) return N-n; -@@ -47,7 +57,5 @@ size_t wcsrtombs(char *restrict s, const wchar_t **restrict ws, size_t n, mbstat - } - (*ws)++; - } -- if (n) *s = 0; -- *ws = 0; -- return N-n; -+ return N; - } -diff --git a/src/network/dns_parse.c b/src/network/dns_parse.c -index aa0d39f..0c7a601 100644 ---- a/src/network/dns_parse.c -+++ b/src/network/dns_parse.c -@@ -6,6 +6,7 @@ int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, c - const unsigned char *p; - int len; - -+ if (rlen<12) return -1; - if ((r[3]&15)) return 0; - p = r+12; - qdcount = r[4]*256 + r[5]; -@@ -13,13 +14,13 @@ int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, c - if (qdcount+ancount > 64) return -1; - while (qdcount--) { - while (p-r < rlen && *p-1U < 127) p++; -- if (*p>193 || (*p==193 && p[1]>254) || p>r+506) -+ if (*p>193 || (*p==193 && p[1]>254) || p>r+rlen-6) - return -1; - p += 5 + !!*p; - } - while (ancount--) { - while (p-r < rlen && *p-1U < 127) p++; -- if (*p>193 || (*p==193 && p[1]>254) || p>r+506) -+ if (*p>193 || (*p==193 && p[1]>254) || p>r+rlen-6) - return -1; - p += 1 + !!*p; - len = p[8]*256 + p[9]; -diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c -index 8d41627..0292093 100644 ---- a/src/network/lookup_name.c -+++ b/src/network/lookup_name.c -@@ -151,7 +151,10 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static - for (i=0; i<nq; i++) - __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); - -- return ctx.cnt; -+ if (ctx.cnt) return ctx.cnt; -+ if (alens[0] < 4 || (abuf[0][3] & 15) == 2) return EAI_AGAIN; -+ if ((abuf[0][3] & 15) == 3) return EAI_NONAME; -+ return EAI_FAIL; - } - - int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags) diff --git a/main/musl/0003-d85d261e-to-2abb70c3.patch b/main/musl/0003-d85d261e-to-2abb70c3.patch deleted file mode 100644 index 0ceecf5eb..000000000 --- a/main/musl/0003-d85d261e-to-2abb70c3.patch +++ /dev/null @@ -1,540 +0,0 @@ -diff --git a/include/netdb.h b/include/netdb.h -index dfc70e2..703a4b2 100644 ---- a/include/netdb.h -+++ b/include/netdb.h -@@ -41,7 +41,7 @@ struct addrinfo - #define NI_NOFQDN 0x04 - #define NI_NAMEREQD 0x08 - #define NI_DGRAM 0x10 --/*#define NI_NUMERICSCOPE */ -+#define NI_NUMERICSCOPE 0x100 - - #define EAI_BADFLAGS -1 - #define EAI_NONAME -2 -diff --git a/src/network/dn_expand.c b/src/network/dn_expand.c -index 96adf37..849df19 100644 ---- a/src/network/dn_expand.c -+++ b/src/network/dn_expand.c -@@ -4,10 +4,11 @@ - int __dn_expand(const unsigned char *base, const unsigned char *end, const unsigned char *src, char *dest, int space) - { - const unsigned char *p = src; -- int len = -1, j; -- if (space > 256) space = 256; -+ char *dend = dest + (space > 254 ? 254 : space); -+ int len = -1, i, j; - if (p==end || !*p) return -1; -- for (;;) { -+ /* detect reference loop using an iteration counter */ -+ for (i=0; i < end-base; i+=2) { - if (*p & 0xc0) { - if (p+1==end) return -1; - j = ((p[0] & 0x3f) << 8) | p[1]; -@@ -16,7 +17,7 @@ int __dn_expand(const unsigned char *base, const unsigned char *end, const unsig - p = base+j; - } else if (*p) { - j = *p+1; -- if (j>=end-p || j>space) return -1; -+ if (j>=end-p || j>dend-dest) return -1; - while (--j) *dest++ = *++p; - *dest++ = *++p ? '.' : 0; - } else { -@@ -24,6 +25,7 @@ int __dn_expand(const unsigned char *base, const unsigned char *end, const unsig - return len; - } - } -+ return -1; - } - - weak_alias(__dn_expand, dn_expand); -diff --git a/src/network/ent.c b/src/network/ent.c -index 4c2f24b..ececdc4 100644 ---- a/src/network/ent.c -+++ b/src/network/ent.c -@@ -16,11 +16,3 @@ void endhostent(void) - weak_alias(sethostent, setnetent); - weak_alias(gethostent, getnetent); - weak_alias(endhostent, endnetent); -- --weak_alias(sethostent, setservent); --weak_alias(gethostent, getservent); --weak_alias(endhostent, endservent); -- --weak_alias(sethostent, setprotoent); --weak_alias(gethostent, getprotoent); --weak_alias(endhostent, endprotoent); -diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c -index 70b6cfd..d991344 100644 ---- a/src/network/getaddrinfo.c -+++ b/src/network/getaddrinfo.c -@@ -105,6 +105,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru - case AF_INET6: - out[k].sa.sin6.sin6_family = AF_INET6; - out[k].sa.sin6.sin6_port = htons(ports[j].port); -+ out[k].sa.sin6.sin6_scope_id = addrs[i].scopeid; - memcpy(&out[k].sa.sin6.sin6_addr, &addrs[i].addr, 16); - break; - } -diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c -index dfcf6ed..588ed76 100644 ---- a/src/network/getnameinfo.c -+++ b/src/network/getnameinfo.c -@@ -5,6 +5,10 @@ - #include <sys/socket.h> - #include <netinet/in.h> - #include <arpa/inet.h> -+#include <net/if.h> -+#include <ctype.h> -+#include "lookup.h" -+#include "stdio_impl.h" - - int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *), void *); - int __dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); -@@ -14,6 +18,16 @@ int __res_send(const unsigned char *, int, unsigned char *, int); - #define PTR_MAX (64 + sizeof ".in-addr.arpa") - #define RR_PTR 12 - -+static char *itoa(char *p, unsigned x) { -+ p += 3*sizeof(int); -+ *--p = 0; -+ do { -+ *--p = '0' + x % 10; -+ x /= 10; -+ } while (x); -+ return p; -+} -+ - static void mkptr4(char *s, const unsigned char *ip) - { - sprintf(s, "%d.%d.%d.%d.in-addr.arpa", -@@ -31,6 +45,72 @@ static void mkptr6(char *s, const unsigned char *ip) - strcpy(s, "ip6.arpa"); - } - -+static void reverse_hosts(char *buf, const unsigned char *a, unsigned scopeid, int family) -+{ -+ char line[512], *p, *z; -+ unsigned char _buf[1032], atmp[16]; -+ struct address iplit; -+ FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf); -+ if (!f) return; -+ if (family == AF_INET) { -+ memcpy(atmp+12, a, 4); -+ memcpy(atmp, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); -+ a = atmp; -+ } -+ while (fgets(line, sizeof line, f)) { -+ if ((p=strchr(line, '#'))) *p++='\n', *p=0; -+ -+ for (p=line; *p && !isspace(*p); p++); -+ *p++ = 0; -+ if (__lookup_ipliteral(&iplit, line, AF_UNSPEC)<=0) -+ continue; -+ -+ if (iplit.family == AF_INET) { -+ memcpy(iplit.addr+12, iplit.addr, 4); -+ memcpy(iplit.addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); -+ iplit.scopeid = 0; -+ } -+ -+ if (memcmp(a, iplit.addr, 16) || iplit.scopeid != scopeid) -+ continue; -+ -+ for (; *p && isspace(*p); p++); -+ for (z=p; *z && !isspace(*z); z++); -+ *z = 0; -+ if (z-p < 256) { -+ memcpy(buf, p, z-p+1); -+ break; -+ } -+ } -+ __fclose_ca(f); -+} -+ -+static void reverse_services(char *buf, int port, int dgram) -+{ -+ unsigned long svport; -+ char line[128], *p, *z; -+ unsigned char _buf[1032]; -+ FILE _f, *f = __fopen_rb_ca("/etc/services", &_f, _buf, sizeof _buf); -+ if (!f) return; -+ while (fgets(line, sizeof line, f)) { -+ if ((p=strchr(line, '#'))) *p++='\n', *p=0; -+ -+ for (p=line; *p && !isspace(*p); p++); -+ if (!p) continue; -+ *p++ = 0; -+ svport = strtoul(p, &z, 10); -+ -+ if (svport != port || z==p) continue; -+ if (dgram && strncmp(z, "/udp", 4)) continue; -+ if (!dgram && strncmp(z, "/tcp", 4)) continue; -+ if (p-line > 32) continue; -+ -+ memcpy(buf, line, p-line); -+ break; -+ } -+ __fclose_ca(f); -+} -+ - static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet) - { - char tmp[256]; -@@ -48,15 +128,17 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, - int flags) - { - char ptr[PTR_MAX]; -- char buf[256]; -+ char buf[256], num[3*sizeof(int)+1]; - int af = sa->sa_family; - unsigned char *a; -+ unsigned scopeid; - - switch (af) { - case AF_INET: - a = (void *)&((struct sockaddr_in *)sa)->sin_addr; - if (sl != sizeof(struct sockaddr_in)) return EAI_FAMILY; - mkptr4(ptr, a); -+ scopeid = 0; - break; - case AF_INET6: - a = (void *)&((struct sockaddr_in6 *)sa)->sin6_addr; -@@ -65,6 +147,7 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, - mkptr6(ptr, a); - else - mkptr4(ptr, a+12); -+ scopeid = ((struct sockaddr_in6 *)sa)->sin6_scope_id; - break; - default: - return EAI_FAMILY; -@@ -73,6 +156,9 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, - if (node && nodelen) { - buf[0] = 0; - if (!(flags & NI_NUMERICHOST)) { -+ reverse_hosts(buf, a, scopeid, af); -+ } -+ if (!*buf && !(flags & NI_NUMERICHOST)) { - unsigned char query[18+PTR_MAX], reply[512]; - int qlen = __res_mkquery(0, ptr, 1, RR_PTR, - 0, 0, 0, query, sizeof query); -@@ -84,16 +170,33 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, - if (!*buf) { - if (flags & NI_NAMEREQD) return EAI_NONAME; - inet_ntop(af, a, buf, sizeof buf); -+ if (scopeid) { -+ char *p = 0, tmp[IF_NAMESIZE+1]; -+ if (!(flags & NI_NUMERICSCOPE) && -+ (IN6_IS_ADDR_LINKLOCAL(a) || -+ IN6_IS_ADDR_MC_LINKLOCAL(a))) -+ p = if_indextoname(scopeid, tmp+1); -+ if (!p) -+ p = itoa(num, scopeid); -+ *--p = '%'; -+ strcat(buf, p); -+ } - } - if (strlen(buf) >= nodelen) return EAI_OVERFLOW; - strcpy(node, buf); - } - - if (serv && servlen) { -- if (snprintf(buf, sizeof buf, "%d", -- ntohs(((struct sockaddr_in *)sa)->sin_port))>=servlen) -+ char *p = buf; -+ int port = ntohs(((struct sockaddr_in *)sa)->sin_port); -+ buf[0] = 0; -+ if (!(flags & NI_NUMERICSERV)) -+ reverse_services(buf, port, flags & NI_DGRAM); -+ if (!*p) -+ p = itoa(num, port); -+ if (strlen(p) >= servlen) - return EAI_OVERFLOW; -- strcpy(serv, buf); -+ strcpy(serv, p); - } - - return 0; -diff --git a/src/network/if_nametoindex.c b/src/network/if_nametoindex.c -index fb4a147..cb6ec05 100644 ---- a/src/network/if_nametoindex.c -+++ b/src/network/if_nametoindex.c -@@ -14,5 +14,5 @@ unsigned if_nametoindex(const char *name) - strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); - r = ioctl(fd, SIOCGIFINDEX, &ifr); - __syscall(SYS_close, fd); -- return r < 0 ? r : ifr.ifr_ifindex; -+ return r < 0 ? 0 : ifr.ifr_ifindex; - } -diff --git a/src/network/lookup.h b/src/network/lookup.h -index 82c969e..19c9e48 100644 ---- a/src/network/lookup.h -+++ b/src/network/lookup.h -@@ -22,5 +22,6 @@ struct service { - - int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int flags); - int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags); -+int __lookup_ipliteral(struct address buf[static 1], const char *name, int family); - - #endif -diff --git a/src/network/lookup_ipliteral.c b/src/network/lookup_ipliteral.c -new file mode 100644 -index 0000000..7bcb85f ---- /dev/null -+++ b/src/network/lookup_ipliteral.c -@@ -0,0 +1,52 @@ -+#include <sys/socket.h> -+#include <netinet/in.h> -+#include <netdb.h> -+#include <net/if.h> -+#include <arpa/inet.h> -+#include <limits.h> -+#include <stdlib.h> -+#include <string.h> -+#include <ctype.h> -+#include "lookup.h" -+ -+int __inet_aton(const char *, struct in_addr *); -+ -+int __lookup_ipliteral(struct address buf[static 1], const char *name, int family) -+{ -+ struct in_addr a4; -+ struct in6_addr a6; -+ if (family != AF_INET6 && __inet_aton(name, &a4)>0) { -+ memcpy(&buf[0].addr, &a4, sizeof a4); -+ buf[0].family = AF_INET; -+ buf[0].scopeid = 0; -+ return 1; -+ } -+ if (family != AF_INET) { -+ char tmp[64]; -+ char *p = strchr(name, '%'), *z; -+ unsigned long long scopeid; -+ if (p && p-name < 64) { -+ memcpy(tmp, name, p-name); -+ tmp[p-name] = 0; -+ name = tmp; -+ } -+ if (inet_pton(AF_INET6, name, &a6)<=0) return 0; -+ memcpy(&buf[0].addr, &a6, sizeof a6); -+ buf[0].family = AF_INET6; -+ if (p) { -+ if (isdigit(*++p)) scopeid = strtoull(p, &z, 10); -+ else z = p-1; -+ if (*z) { -+ if (!IN6_IS_ADDR_LINKLOCAL(&a6) && -+ !IN6_IS_ADDR_MC_LINKLOCAL(&a6)) -+ return EAI_NONAME; -+ scopeid = if_nametoindex(p); -+ if (!scopeid) return EAI_NONAME; -+ } -+ if (scopeid > UINT_MAX) return EAI_NONAME; -+ buf[0].scopeid = scopeid; -+ } -+ return 1; -+ } -+ return 0; -+} -diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c -index 0292093..68b172b 100644 ---- a/src/network/lookup_name.c -+++ b/src/network/lookup_name.c -@@ -1,6 +1,7 @@ - #include <sys/socket.h> - #include <netinet/in.h> - #include <netdb.h> -+#include <net/if.h> - #include <arpa/inet.h> - #include <ctype.h> - #include <stdlib.h> -@@ -13,7 +14,7 @@ - static int is_valid_hostname(const char *host) - { - const unsigned char *s; -- if (strnlen(host, 256)-1 > 254 || mbstowcs(0, host, 0) > 255) return 0; -+ if (strnlen(host, 254)-1 >= 253 || mbstowcs(0, host, 0) == -1) return 0; - for (s=(void *)host; *s>=0x80 || *s=='.' || *s=='-' || isalnum(*s); s++); - return !*s; - } -@@ -36,23 +37,9 @@ static int name_from_null(struct address buf[static 2], const char *name, int fa - return cnt; - } - --int __inet_aton(const char *, struct in_addr *); -- - static int name_from_numeric(struct address buf[static 1], const char *name, int family) - { -- struct in_addr a4; -- struct in6_addr a6; -- if (family != AF_INET6 && __inet_aton(name, &a4)>0) { -- memcpy(&buf[0].addr, &a4, sizeof a4); -- buf[0].family = AF_INET; -- return 1; -- } -- if (family != AF_INET && inet_pton(AF_INET6, name, &a6)>0) { -- memcpy(&buf[0].addr, &a6, sizeof a6); -- buf[0].family = AF_INET6; -- return 1; -- } -- return 0; -+ return __lookup_ipliteral(buf, name, family); - } - - static int name_from_hosts(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) -@@ -110,11 +97,13 @@ static int dns_parse_callback(void *c, int rr, const void *data, int len, const - case RR_A: - if (len != 4) return -1; - ctx->addrs[ctx->cnt].family = AF_INET; -+ ctx->addrs[ctx->cnt].scopeid = 0; - memcpy(ctx->addrs[ctx->cnt++].addr, data, 4); - break; - case RR_AAAA: - if (len != 16) return -1; - ctx->addrs[ctx->cnt].family = AF_INET6; -+ ctx->addrs[ctx->cnt].scopeid = 0; - memcpy(ctx->addrs[ctx->cnt++].addr, data, 16); - break; - case RR_CNAME: -@@ -164,7 +153,7 @@ int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], c - *canon = 0; - if (name) { - size_t l; -- if ((l = strnlen(name, 256))-1 > 254) -+ if ((l = strnlen(name, 254))-1 >= 253) - return EAI_NONAME; - memcpy(canon, name, l+1); - } -@@ -179,10 +168,10 @@ int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], c - - /* Try each backend until there's at least one result. */ - cnt = name_from_null(buf, name, family, flags); -- if (cnt<=0) cnt = name_from_numeric(buf, name, family); -- if (cnt<=0 && !(flags & AI_NUMERICHOST)) { -+ if (!cnt) cnt = name_from_numeric(buf, name, family); -+ if (!cnt && !(flags & AI_NUMERICHOST)) { - cnt = name_from_hosts(buf, canon, name, family); -- if (cnt<=0) cnt = name_from_dns(buf, canon, name, family); -+ if (!cnt) cnt = name_from_dns(buf, canon, name, family); - } - if (cnt<=0) return cnt ? cnt : EAI_NONAME; - -@@ -204,7 +193,6 @@ int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], c - if (buf[i].family != AF_INET) continue; - memcpy(buf[i].addr+12, buf[i].addr, 4); - memcpy(buf[i].addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); -- buf[i].scopeid = 0; - buf[i].family = AF_INET6; - } - } -diff --git a/src/network/res_mkquery.c b/src/network/res_mkquery.c -index f7e4e9c..7c49709 100644 ---- a/src/network/res_mkquery.c -+++ b/src/network/res_mkquery.c -@@ -10,9 +10,9 @@ int __res_mkquery(int op, const char *dname, int class, int type, - int id, i, j; - unsigned char q[280]; - struct timespec ts; -- size_t l = strnlen(dname, 256); -+ size_t l = strnlen(dname, 254); - -- if (l-1>=254 || buflen<18+l || op>15u || class>255u || type>255u) -+ if (l-1>=253 || buflen<18+l || op>15u || class>255u || type>255u) - return -1; - - /* Construct query template - ID will be filled later */ -diff --git a/src/network/res_msend.c b/src/network/res_msend.c -index a5b7793..5192b4d 100644 ---- a/src/network/res_msend.c -+++ b/src/network/res_msend.c -@@ -12,6 +12,7 @@ - #include <pthread.h> - #include "stdio_impl.h" - #include "syscall.h" -+#include "lookup.h" - - static void cleanup(void *p) - { -@@ -47,6 +48,7 @@ int __res_msend(int nqueries, const unsigned char *const *queries, - int cs; - struct pollfd pfd; - unsigned long t0, t1, t2; -+ struct address iplit; - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); - -@@ -76,13 +78,18 @@ int __res_msend(int nqueries, const unsigned char *const *queries, - for (z=s; *z && !isspace(*z); z++); - *z=0; - -- if (inet_pton(AF_INET, s, &ns[nns].sin.sin_addr)>0) { -- ns[nns].sin.sin_port = htons(53); -- ns[nns++].sin.sin_family = AF_INET; -- } else if (inet_pton(AF_INET6, s, &ns[nns].sin6.sin6_addr)>0) { -- sl = sizeof sa.sin6; -- ns[nns].sin6.sin6_port = htons(53); -- ns[nns++].sin6.sin6_family = family = AF_INET6; -+ if (__lookup_ipliteral(&iplit, s, AF_UNSPEC)>0) { -+ if (iplit.family == AF_INET) { -+ memcpy(&ns[nns].sin.sin_addr, iplit.addr, 4); -+ ns[nns].sin.sin_port = htons(53); -+ ns[nns++].sin.sin_family = AF_INET; -+ } else { -+ sl = sizeof sa.sin6; -+ memcpy(&ns[nns].sin6.sin6_addr, iplit.addr, 16); -+ ns[nns].sin6.sin6_port = htons(53); -+ ns[nns].sin6.sin6_scope_id = iplit.scopeid; -+ ns[nns++].sin6.sin6_family = family = AF_INET6; -+ } - } - } - if (f) __fclose_ca(f); -diff --git a/src/network/res_querydomain.c b/src/network/res_querydomain.c -index c746dbe..8ba31f4 100644 ---- a/src/network/res_querydomain.c -+++ b/src/network/res_querydomain.c -@@ -3,10 +3,10 @@ - - int res_querydomain(const char *name, const char *domain, int class, int type, unsigned char *dest, int len) - { -- char tmp[256]; -- size_t nl = strnlen(name, 256); -- size_t dl = strnlen(domain, 256); -- if (nl+dl+1 > 255) return -1; -+ char tmp[254]; -+ size_t nl = strnlen(name, 254); -+ size_t dl = strnlen(domain, 254); -+ if (nl+dl+1 > 253) return -1; - memcpy(tmp, name, nl); - tmp[nl] = '.'; - memcpy(tmp+nl+1, domain, dl+1); -diff --git a/src/stdio/vasprintf.c b/src/stdio/vasprintf.c -index 68b7246..08251bc 100644 ---- a/src/stdio/vasprintf.c -+++ b/src/stdio/vasprintf.c -@@ -3,26 +3,13 @@ - #include <stdarg.h> - #include <stdlib.h> - --#define GUESS 240U -- - int vasprintf(char **s, const char *fmt, va_list ap) - { - va_list ap2; -- char *a; -- int l=GUESS; -- -- if (!(a=malloc(GUESS))) return -1; -- - va_copy(ap2, ap); -- l=vsnprintf(a, GUESS, fmt, ap2); -+ int l = vsnprintf(0, 0, fmt, ap2); - va_end(ap2); - -- if (l<GUESS) { -- char *b = realloc(a, l+1U); -- *s = b ? b : a; -- return l; -- } -- free(a); - if (l<0 || !(*s=malloc(l+1U))) return -1; - return vsnprintf(*s, l+1U, fmt, ap); - } diff --git a/main/musl/1003-implement-y-and-C-specifiers-in-strptime.patch b/main/musl/1003-implement-y-and-C-specifiers-in-strptime.patch deleted file mode 100644 index f8c78a090..000000000 --- a/main/musl/1003-implement-y-and-C-specifiers-in-strptime.patch +++ /dev/null @@ -1,64 +0,0 @@ -From c133ba2ee8a937ed4db438360f2f78d0a8cb9a24 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> -Date: Wed, 14 May 2014 10:53:56 +0300 -Subject: [PATCH] implement %y and %C specifiers in strptime - ---- - src/time/strptime.c | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - -diff --git a/src/time/strptime.c b/src/time/strptime.c -index 4d9eea4..f41f55f 100644 ---- a/src/time/strptime.c -+++ b/src/time/strptime.c -@@ -11,6 +11,7 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri - int i, w, neg, adj, min, range, *dest, dummy; - const char *ex; - size_t len; -+ int want_century = 0, century = 0; - while (*f) { - if (*f != '%') { - if (isspace(*f)) for (; *s && isspace(*s); s++); -@@ -40,9 +41,9 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri - if (!s) return 0; - break; - case 'C': -- /* FIXME */ -- dest = &dummy; -+ dest = ¢ury; - if (w<0) w=2; -+ want_century |= 2; - goto numeric_digits; - case 'd': case 'e': - dest = &tm->tm_mday; -@@ -135,14 +136,15 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri - if (!s) return 0; - break; - case 'y': -- /* FIXME */ -- dest = &dummy; -+ dest = &tm->tm_year; - w = 2; -+ want_century |= 1; - goto numeric_digits; - case 'Y': - dest = &tm->tm_year; - if (w<0) w=4; - adj = 1900; -+ want_century = 0; - goto numeric_digits; - case '%': - if (*s++ != '%') return 0; -@@ -187,5 +189,9 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri - ; - } - } -+ if (want_century) { -+ if (want_century & 2) tm->tm_year += century * 100 - 1900; -+ else if (tm->tm_year <= 68) tm->tm_year += 100; -+ } - return (char *)s; - } --- -1.9.3 - diff --git a/main/musl/APKBUILD b/main/musl/APKBUILD index 450d0d3d8..80968cabb 100644 --- a/main/musl/APKBUILD +++ b/main/musl/APKBUILD @@ -1,8 +1,8 @@ # Contributor: William Pitcock <nenolod@dereferenced.org> # Maintainer: Timo Teräs <timo.teras@iki.fi> pkgname=musl -pkgver=1.1.1 -pkgrel=3 +pkgver=1.1.2 +pkgrel=0 pkgdesc="the musl c library (libc) implementation" url="http://www.musl-libc.org/" arch="all" @@ -13,12 +13,8 @@ makedepends="$depends_dev" install="" subpackages="$pkgname-dev $pkgname-utils" source="http://www.musl-libc.org/releases/musl-$pkgver.tar.gz - 0001-v1.1.1-to-76f440cf.patch - 0002-76f440cf-to-d85d261e.patch - 0003-d85d261e-to-2abb70c3.patch 1001-add-basic-dns-record-parsing-functions.patch 1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch - 1003-implement-y-and-C-specifiers-in-strptime.patch 2001-default-to-localtime-timezone-if-TZ-is-undefined.patch ldconfig @@ -120,13 +116,9 @@ utils() { install -D -m755 "$srcdir"/ldconfig "$subpkgdir"/sbin } -md5sums="dbc08d311148e095016d9bbf6c7ffda6 musl-1.1.1.tar.gz -d4a40fe1656115b2956065ab48e0b372 0001-v1.1.1-to-76f440cf.patch -0b0dce47217fe25eeb82a7f70e15629f 0002-76f440cf-to-d85d261e.patch -4e7a277d2aa6ca246bca81996f247379 0003-d85d261e-to-2abb70c3.patch +md5sums="a81309e54efdf9c68baf679790fc5678 musl-1.1.2.tar.gz a3810683ef61ac27e2f6ec9801280c81 1001-add-basic-dns-record-parsing-functions.patch 83c3bd2a50b1de5ef948704d3f4e0583 1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch -fc3feec4104a4b25781df92dd96b9eec 1003-implement-y-and-C-specifiers-in-strptime.patch e936297ceb484b2160a4cd8a3a4eb291 2001-default-to-localtime-timezone-if-TZ-is-undefined.patch 013be8897f27c3909ada59c62020502f ldconfig 61c6c1e84ed1df82abbe6d75e90cf21c getopt_long.c @@ -134,13 +126,9 @@ e936297ceb484b2160a4cd8a3a4eb291 2001-default-to-localtime-timezone-if-TZ-is-un cb82d21fed17a116b44b830adba71c5a getconf.c 2b941c4251cac44988a4abfc50e21267 getent.c 45f92f8d59cf84d765de698a9578dbf4 iconv.c" -sha256sums="9dd75d6512e44d5a13254e246db56c90365894b05bab2b1127e44a31e4fd7c36 musl-1.1.1.tar.gz -40f241a8aa59621d8a9e6a616df27c38e0a622243bf7346cc98ec1c37454e92a 0001-v1.1.1-to-76f440cf.patch -d0f4dbc8f0e72df02fcb12e75f829d50909c6da222a5f6a13a0e0c991f91d56e 0002-76f440cf-to-d85d261e.patch -b931c40613923925ac28a010e4ffbe13380a056dfd01eeccc3a090f598edeaff 0003-d85d261e-to-2abb70c3.patch +sha256sums="dac94112b9a22d2657cd3f36ca0d62ee1eb10707a22bfc97d5746147ef92852b musl-1.1.2.tar.gz 758390768b1bc4159d56908ca332b9640cd0552ed3b4b2b8d4a6d499c54c11a1 1001-add-basic-dns-record-parsing-functions.patch 1c25880095e869b827f02997e864fdf4bf157a4e923e52d97dbd05e657aedb70 1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch -c22338bc33e8c0c22b280c392b37a0903e13562e671f5ebade09ed5b1d33e2ae 1003-implement-y-and-C-specifiers-in-strptime.patch 60d7aa78040ee664681e507475129f76e445291863137e568c9a3d11ae8436ce 2001-default-to-localtime-timezone-if-TZ-is-undefined.patch 398dc26ec82cc6af056c738e8ac62da212ba978229d9839eb8b61f7ce536da4a ldconfig d9b644ec20bc33e81a7c52b9fcf7973d835923a69faf50f03db45534b811bd96 getopt_long.c @@ -148,13 +136,9 @@ d9b644ec20bc33e81a7c52b9fcf7973d835923a69faf50f03db45534b811bd96 getopt_long.c 1b540709f83b7b9a03073b39066810fdb90537d840b50c2016a84bedce038606 getconf.c 68373a55e89ce85c562d941ccf588337d6cc6c9c17689d695f65cd7607134bbe getent.c f79a2930a2e5bb0624321589edf8b889d1e9b603e01e6b7ae214616605b3fdd7 iconv.c" -sha512sums="5182deb80a35c8a4009d71098c95a16e5ab9bd03186443917652f0c521d2980183e203256493a69e8230b6a0c4848ca8e44de9e8c851a511cd37d0d41f91b14f musl-1.1.1.tar.gz -30906a5f7a01ff05693e5a2e72f6c7e75ff7939c28a32b9e777d14d59412bb9df603a09aa8dd693e9a0b70525474a62f7bc657425032a3a5f4b339667e6f62ec 0001-v1.1.1-to-76f440cf.patch -358f3828367f5a86806ce5be5842c2be44c1a7919133ab83a7c549bc55be847fee2a938c201782db771ff6a5a994cab6ee7c2050f6ae564f4993c0b3825faa36 0002-76f440cf-to-d85d261e.patch -5bba3f6e369ae38536634cc181b629158dab515476577617024c585ad2247f17bec79b9de035063bddddad07df204654b7eae829b6deb856867907c762f5d2c7 0003-d85d261e-to-2abb70c3.patch +sha512sums="54d279efea6e122567c936e47401df5c0f1493c42eb3199b0ba3053b1882a864fc1a71d19ad945bc4f328407231c54a7897413e37f4bc33337a243c044a26b4a musl-1.1.2.tar.gz dad965258daf69371b844f76bfe5a914b0eca0ca76f3fc340b8fd7acf598b5f87bbe6d68b1f43ed0293ee0ed3bfd85d5173ccc169aa6265646248d5b8a906708 1001-add-basic-dns-record-parsing-functions.patch 72cf33738d2cf31f6ec02312bc494d754c17470b519172bb8bd7e2e29ac3b119023088a2b3fbc0dbc2fddd0078ccbae62096106cae361f8c31d6a9950043af25 1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch -48082d2348de40bc6b455266c5552a62e1e75f926e69116c61c8a3cb35fefdff136dc771bf25ee7d43c959834921221112ed7afcc45fcadbcf07562510786916 1003-implement-y-and-C-specifiers-in-strptime.patch 8d4cae760895a18e83b5fcbdc925705a6dd98acd2270562ee6c905363096a4111cf3aa324b52a16066e30bddc9ab104883e2b25b5c68396ea27f1c50cb939f0a 2001-default-to-localtime-timezone-if-TZ-is-undefined.patch 33e13d2242063f3dc9ec199ae9528e469a52ccae4d3726faa3c866e0c7dcf546f69294f9c00307324cee05fd965f84350ae100b8b1138f9d9c8c916de04ab0d1 ldconfig 140f3f20d30bd95ebce8c41b8cc7f616c6cbedf4ea06c729c21014e74f6043796825cc40ebc5180620ea38173afdba23f09ebf6d8b11fa05440b14d23764fca9 getopt_long.c |