This is an automated email from the git hooks/post-receive script. aurel32 pushed a commit to branch glibc-2.26 in repository glibc.
commit d52a330c4cea79690233af54f8f65929abbc3ae5 Author: Aurelien Jarno <aurel...@aurel32.net> Date: Sun Dec 31 19:11:21 2017 +0100 debian/patches/git-updates.diff: update from upstream stable branch. --- debian/changelog | 1 + debian/patches/git-updates.diff | 3281 +++++++++++++++++++++++++++++++++------ 2 files changed, 2848 insertions(+), 434 deletions(-) diff --git a/debian/changelog b/debian/changelog index 3158f20..1c30857 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,6 +10,7 @@ glibc (2.26-0experimental3) UNRELEASED; urgency=medium * debian/sysdeps/hppa.mk: set TIMEOUTFACTOR to 100 on HPPA. * debian/testsuite-xfail-debian.mk: remove tst-create-detached from XFAIL on HPPA. + * debian/patches/git-updates.diff: update from upstream stable branch. -- Aurelien Jarno <aure...@debian.org> Sun, 17 Dec 2017 20:13:55 +0100 diff --git a/debian/patches/git-updates.diff b/debian/patches/git-updates.diff index e112efc..753fa61 100644 --- a/debian/patches/git-updates.diff +++ b/debian/patches/git-updates.diff @@ -1,10 +1,70 @@ -GIT update of git://sourceware.org/git/glibc.git/release/2.26/master from glibc-2.26 +GIT update of https://sourceware.org/git/glibc.git/release/2.26/master from glibc-2.26 diff --git a/ChangeLog b/ChangeLog -index 8dbfc7eaff..55a17414ab 100644 +index 8dbfc7eaff..414e931aa5 100644 --- a/ChangeLog +++ b/ChangeLog -@@ -1,3 +1,1057 @@ +@@ -1,3 +1,1117 @@ ++2017-12-30 Aurelien Jarno <aurel...@aurel32.net> ++ Dmitry V. Levin <l...@altlinux.org> ++ ++ [BZ #22625] ++ * elf/dl-load.c (fillin_rpath): Check for empty tokens before dynamic ++ string token expansion. Check for NULL pointer or empty string possibly ++ returned by expand_dynamic_string_token. ++ (decompose_rpath): Check for empty path after dynamic string ++ token expansion. ++ ++2017-12-18 Dmitry V. Levin <l...@altlinux.org> ++ ++ [BZ #22627] ++ * elf/dl-load.c (_dl_init_paths): Remove _dl_dst_substitute preparatory ++ code and invocation. ++ ++2017-11-18 Florian Weimer <fwei...@redhat.com> ++ ++ * sysdeps/unix/sysv/linux/tst-ttyname.c ++ (become_root_in_mount_ns): Remove. ++ (do_in_chroot_1): Call support_enter_mount_namespace. ++ (do_in_chroot_2): Likewise. ++ (do_test): Call support_become_root early. ++ ++2017-11-15 Luke Shumaker <luke...@parabola.nu> ++ ++ [BZ #22145] ++ * sysdeps/unix/sysv/linux/tst-ttyname.c: New file. ++ * sysdeps/unix/sysv/linux/Makefile: Add tst-ttyname to tests. ++ ++2017-11-15 Luke Shumaker <luke...@parabola.nu> ++ ++ [BZ #22145] ++ * sysdeps/unix/sysv/linux/ttyname.c (ttyname): ++ Defer is_pty check until end of the function. ++ * sysdeps/unix/sysv/linux/ttyname_r.c (__ttyname_r): Likewise. ++ ++2017-11-15 Luke Shumaker <luke...@parabola.nu> ++ ++ [BZ #22145] ++ * sysdeps/unix/sysv/linux/ttyname.h (is_mytty): New function. ++ * sysdeps/unix/sysv/linux/ttyname.c (getttyname): Call is_mytty. ++ (ttyname): Likewise. ++ * sysdeps/unix/sysv/linux/ttyname_r.c (getttyname_r): Likewise. ++ (__ttyname_r): Likewise. ++ ++2017-11-15 Luke Shumaker <luke...@parabola.nu> ++ ++ * sysdeps/unix/sysv/linux/ttyname.h (is_pty): Change return type from ++ int to bool. ++ ++2017-11-15 Luke Shumaker <luke...@parabola.nu> ++ ++ * sysdeps/unix/sysv/linux/ttyname.h (is_pty): Update doc reference. ++ ++2017-11-15 Luke Shumaker <luke...@parabola.nu> ++ ++ * manual/terminal.texi (Is It a Terminal): ++ Mention ENODEV for ttyname and ttyname_r. ++ +2017-12-14 Florian Weimer <fwei...@redhat.com> + + [BZ #22607] @@ -1086,10 +1146,10 @@ index 9bb707c168..828a445f24 100644 # Don't try to use -lc when making libc.so itself. # Also omits crti.o and crtn.o, which we do not want diff --git a/NEWS b/NEWS -index 8295f20c0a..2c49212cb5 100644 +index 8295f20c0a..f04b3ed4e8 100644 --- a/NEWS +++ b/NEWS -@@ -5,6 +5,92 @@ See the end for copying conditions. +@@ -5,6 +5,98 @@ See the end for copying conditions. Please send GNU C library bug reports via <http://sourceware.org/bugzilla/> using `glibc' in the "product" field. @@ -1143,6 +1203,10 @@ index 8295f20c0a..2c49212cb5 100644 + CVE-2017-1000366 has been applied, but it is mentioned here only because + of the CVE assignment.) Reported by Qualys. + ++ CVE-2017-16997: Incorrect handling of RPATH or RUNPATH containing $ORIGIN ++ for AT_SECURE or SUID binaries could be used to load libraries from the ++ current directory. ++ +The following bugs are resolved with this release: + + [16750] ldd: Never run file directly. @@ -1168,6 +1232,7 @@ index 8295f20c0a..2c49212cb5 100644 + [22095] resolv: Fix memory leak with OOM during resolv.conf parsing + [22096] resolv: __resolv_conf_attach must not free passed conf object + [22111] malloc: per thread cache is not returned when thread exits ++ [22145] ttyname gives up too early in the face of namespaces + [22146] Let fpclassify use the builtin when optimizing for size in C++ mode + [22225] math: nearbyint arithmetic moved before feholdexcept + [22235] Add C++ versions of iscanonical for ldbl-96 and ldbl-128ibm @@ -1178,6 +1243,7 @@ index 8295f20c0a..2c49212cb5 100644 + [22322] libc: [mips64] wrong bits/long-double.h installed + [22325] glibc: Memory leak in glob with GLOB_TILDE (CVE-2017-15671) + [22375] malloc returns pointer from tcache instead of NULL (CVE-2017-17426) ++ [22627] $ORIGIN in $LD_LIBRARY_PATH is substituted twice + Version 2.26 @@ -1414,7 +1480,7 @@ index 0280fba8a7..8bbbf2a121 100644 else libcrypt-routines += md5 sha256 sha512 diff --git a/elf/dl-load.c b/elf/dl-load.c -index c1b6d4ba0f..621403c05f 100644 +index c1b6d4ba0f..7397c1882c 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -37,6 +37,7 @@ @@ -1447,7 +1513,79 @@ index c1b6d4ba0f..621403c05f 100644 static bool is_trusted_path (const char *path, size_t len) -@@ -688,9 +689,8 @@ _dl_init_paths (const char *llp) +@@ -433,31 +434,40 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, + { + char *cp; + size_t nelems = 0; +- char *to_free; + + while ((cp = __strsep (&rpath, sep)) != NULL) + { + struct r_search_path_elem *dirp; ++ char *to_free = NULL; ++ size_t len = 0; + +- to_free = cp = expand_dynamic_string_token (l, cp, 1); ++ /* `strsep' can pass an empty string. */ ++ if (*cp != '\0') ++ { ++ to_free = cp = expand_dynamic_string_token (l, cp, 1); + +- size_t len = strlen (cp); ++ /* expand_dynamic_string_token can return NULL in case of empty ++ path or memory allocation failure. */ ++ if (cp == NULL) ++ continue; + +- /* `strsep' can pass an empty string. This has to be +- interpreted as `use the current directory'. */ +- if (len == 0) +- { +- static const char curwd[] = "./"; +- cp = (char *) curwd; +- } ++ /* Compute the length after dynamic string token expansion and ++ ignore empty paths. */ ++ len = strlen (cp); ++ if (len == 0) ++ { ++ free (to_free); ++ continue; ++ } + +- /* Remove trailing slashes (except for "/"). */ +- while (len > 1 && cp[len - 1] == '/') +- --len; ++ /* Remove trailing slashes (except for "/"). */ ++ while (len > 1 && cp[len - 1] == '/') ++ --len; + +- /* Now add one if there is none so far. */ +- if (len > 0 && cp[len - 1] != '/') +- cp[len++] = '/'; ++ /* Now add one if there is none so far. */ ++ if (len > 0 && cp[len - 1] != '/') ++ cp[len++] = '/'; ++ } + + /* Make sure we don't use untrusted directories if we run SUID. */ + if (__glibc_unlikely (check_trusted) && !is_trusted_path (cp, len)) +@@ -621,6 +631,14 @@ decompose_rpath (struct r_search_path_struct *sps, + necessary. */ + free (copy); + ++ /* There is no path after expansion. */ ++ if (result[0] == NULL) ++ { ++ free (result); ++ sps->dirs = (struct r_search_path_elem **) -1; ++ return false; ++ } ++ + sps->dirs = result; + /* The caller will change this value if we haven't used a real malloc. */ + sps->malloced = 1; +@@ -688,9 +706,8 @@ _dl_init_paths (const char *llp) + ncapstr * sizeof (enum r_dir_status)) / sizeof (struct r_search_path_elem)); @@ -1459,16 +1597,32 @@ index c1b6d4ba0f..621403c05f 100644 if (rtld_search_dirs.dirs[0] == NULL) { errstring = N_("cannot create cache for search path"); -@@ -776,8 +776,6 @@ _dl_init_paths (const char *llp) +@@ -776,37 +793,14 @@ _dl_init_paths (const char *llp) if (llp != NULL && *llp != '\0') { - size_t nllp; - const char *cp = llp; - char *llp_tmp; - - #ifdef SHARED -@@ -800,13 +798,10 @@ _dl_init_paths (const char *llp) +- char *llp_tmp; +- +-#ifdef SHARED +- /* Expand DSTs. */ +- size_t cnt = DL_DST_COUNT (llp, 1); +- if (__glibc_likely (cnt == 0)) +- llp_tmp = strdupa (llp); +- else +- { +- /* Determine the length of the substituted string. */ +- size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt); +- +- /* Allocate the necessary memory. */ +- llp_tmp = (char *) alloca (total + 1); +- llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1); +- } +-#else +- llp_tmp = strdupa (llp); +-#endif ++ char *llp_tmp = strdupa (llp); /* Decompose the LD_LIBRARY_PATH contents. First determine how many elements it has. */ @@ -10985,11 +11139,237 @@ index e28b0c5058..4320336c9a 100644 #endif } +diff --git a/support/Makefile b/support/Makefile +index 2ace3fa8cc..8458840cd8 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -32,15 +32,18 @@ libsupport-routines = \ + check_netent \ + delayed_exit \ + ignore_stderr \ ++ next_to_fault \ + oom_error \ + resolv_test \ + set_fortify_handler \ ++ support-xfstat \ + support-xstat \ + support_become_root \ + support_can_chroot \ + support_capture_subprocess \ + support_capture_subprocess_check \ + support_chroot \ ++ support_enter_mount_namespace \ + support_enter_network_namespace \ + support_format_address_family \ + support_format_addrinfo \ +@@ -52,6 +55,7 @@ libsupport-routines = \ + support_record_failure \ + support_run_diff \ + support_shared_allocate \ ++ support_test_compare_failure \ + support_write_file_string \ + support_test_main \ + support_test_verify_impl \ +@@ -65,12 +69,15 @@ libsupport-routines = \ + xchroot \ + xclose \ + xconnect \ ++ xdlfcn \ + xdup2 \ + xfclose \ + xfopen \ + xfork \ ++ xftruncate \ + xgetsockname \ + xlisten \ ++ xlseek \ + xmalloc \ + xmemstream \ + xmkdir \ +@@ -83,8 +90,8 @@ libsupport-routines = \ + xpthread_attr_destroy \ + xpthread_attr_init \ + xpthread_attr_setdetachstate \ +- xpthread_attr_setstacksize \ + xpthread_attr_setguardsize \ ++ xpthread_attr_setstacksize \ + xpthread_barrier_destroy \ + xpthread_barrier_init \ + xpthread_barrier_wait \ +@@ -108,19 +115,26 @@ libsupport-routines = \ + xpthread_once \ + xpthread_rwlock_init \ + xpthread_rwlock_rdlock \ +- xpthread_rwlock_wrlock \ + xpthread_rwlock_unlock \ ++ xpthread_rwlock_wrlock \ + xpthread_rwlockattr_init \ + xpthread_rwlockattr_setkind_np \ + xpthread_sigmask \ + xpthread_spin_lock \ + xpthread_spin_unlock \ ++ xraise \ ++ xreadlink \ + xrealloc \ + xrecvfrom \ + xsendto \ + xsetsockopt \ ++ xsigaction \ ++ xsignal \ + xsocket \ + xstrdup \ ++ xstrndup \ ++ xsysconf \ ++ xunlink \ + xwaitpid \ + xwrite \ + +@@ -137,6 +151,8 @@ tests = \ + tst-support_capture_subprocess \ + tst-support_format_dns_packet \ + tst-support_record_failure \ ++ tst-test_compare \ ++ tst-xreadlink \ + + ifeq ($(run-built-tests),yes) + tests-special = \ +diff --git a/support/check.h b/support/check.h +index bdcd12952a..55a6f09f42 100644 +--- a/support/check.h ++++ b/support/check.h +@@ -86,6 +86,67 @@ void support_test_verify_exit_impl (int status, const char *file, int line, + does not support reporting failures from a DSO. */ + void support_record_failure (void); + ++/* Compare the two integers LEFT and RIGHT and report failure if they ++ are different. */ ++#define TEST_COMPARE(left, right) \ ++ ({ \ ++ /* + applies the integer promotions, for bitfield support. */ \ ++ typedef __typeof__ (+ (left)) __left_type; \ ++ typedef __typeof__ (+ (right)) __right_type; \ ++ __left_type __left_value = (left); \ ++ __right_type __right_value = (right); \ ++ /* Prevent use with floating-point and boolean types. */ \ ++ _Static_assert ((__left_type) 1.0 == (__left_type) 1.5, \ ++ "left value has floating-point type"); \ ++ _Static_assert ((__right_type) 1.0 == (__right_type) 1.5, \ ++ "right value has floating-point type"); \ ++ /* Prevent accidental use with larger-than-long long types. */ \ ++ _Static_assert (sizeof (__left_value) <= sizeof (long long), \ ++ "left value fits into long long"); \ ++ _Static_assert (sizeof (__right_value) <= sizeof (long long), \ ++ "right value fits into long long"); \ ++ /* Make sure that integer conversions does not alter the sign. */ \ ++ enum \ ++ { \ ++ __left_is_unsigned = (__left_type) -1 > 0, \ ++ __right_is_unsigned = (__right_type) -1 > 0, \ ++ __unsigned_left_converts_to_wider = (__left_is_unsigned \ ++ && (sizeof (__left_value) \ ++ < sizeof (__right_value))), \ ++ __unsigned_right_converts_to_wider = (__right_is_unsigned \ ++ && (sizeof (__right_value) \ ++ < sizeof (__left_value))) \ ++ }; \ ++ _Static_assert (__left_is_unsigned == __right_is_unsigned \ ++ || __unsigned_left_converts_to_wider \ ++ || __unsigned_right_converts_to_wider, \ ++ "integer conversions may alter sign of operands"); \ ++ /* Compare the value. */ \ ++ if (__left_value != __right_value) \ ++ /* Pass the sign for printing the correct value. */ \ ++ support_test_compare_failure \ ++ (__FILE__, __LINE__, \ ++ #left, __left_value, __left_value < 0, sizeof (__left_type), \ ++ #right, __right_value, __right_value < 0, sizeof (__right_type)); \ ++ }) ++ ++/* Internal implementation of TEST_COMPARE. LEFT_NEGATIVE and ++ RIGHT_NEGATIVE are used to store the sign separately, so that both ++ unsigned long long and long long arguments fit into LEFT_VALUE and ++ RIGHT_VALUE, and the function can still print the original value. ++ LEFT_SIZE and RIGHT_SIZE specify the size of the argument in bytes, ++ for hexadecimal formatting. */ ++void support_test_compare_failure (const char *file, int line, ++ const char *left_expr, ++ long long left_value, ++ int left_negative, ++ int left_size, ++ const char *right_expr, ++ long long right_value, ++ int right_negative, ++ int right_size); ++ ++ + /* Internal function called by the test driver. */ + int support_report_failure (int status) + __attribute__ ((weak, warn_unused_result)); +diff --git a/support/check_addrinfo.c b/support/check_addrinfo.c +index 55895ace3c..c47f105ce6 100644 +--- a/support/check_addrinfo.c ++++ b/support/check_addrinfo.c +@@ -20,6 +20,7 @@ + + #include <stdio.h> + #include <stdlib.h> ++#include <string.h> + #include <support/check.h> + #include <support/format_nss.h> + #include <support/run_diff.h> +diff --git a/support/check_dns_packet.c b/support/check_dns_packet.c +index d2a31bed7b..6d14bd90c0 100644 +--- a/support/check_dns_packet.c ++++ b/support/check_dns_packet.c +@@ -20,6 +20,7 @@ + + #include <stdio.h> + #include <stdlib.h> ++#include <string.h> + #include <support/check.h> + #include <support/format_nss.h> + #include <support/run_diff.h> +diff --git a/support/check_hostent.c b/support/check_hostent.c +index 890d672d50..47fb8bc332 100644 +--- a/support/check_hostent.c ++++ b/support/check_hostent.c +@@ -20,6 +20,7 @@ + + #include <stdio.h> + #include <stdlib.h> ++#include <string.h> + #include <support/check.h> + #include <support/format_nss.h> + #include <support/run_diff.h> +diff --git a/support/check_netent.c b/support/check_netent.c +index daa3083fd1..80b69309b4 100644 +--- a/support/check_netent.c ++++ b/support/check_netent.c +@@ -20,6 +20,7 @@ + + #include <stdio.h> + #include <stdlib.h> ++#include <string.h> + #include <support/check.h> + #include <support/format_nss.h> + #include <support/run_diff.h> diff --git a/support/namespace.h b/support/namespace.h -index 859c2fda3f..9eddb1a0e9 100644 +index 859c2fda3f..b5e2d1474a 100644 --- a/support/namespace.h +++ b/support/namespace.h -@@ -66,7 +66,9 @@ struct support_chroot_configuration +@@ -51,6 +51,11 @@ bool support_can_chroot (void); + has sufficient privileges. */ + bool support_enter_network_namespace (void); + ++/* Enter a mount namespace and mark / as private (not shared). If ++ this function returns true, mount operations in this process will ++ not affect the host system afterwards. */ ++bool support_enter_mount_namespace (void); ++ + /* Return true if support_enter_network_namespace managed to enter a + UTS namespace. */ + bool support_in_uts_namespace (void); +@@ -66,7 +71,9 @@ struct support_chroot_configuration { /* File contents. The files are not created if the field is NULL. */ @@ -11000,7 +11380,7 @@ index 859c2fda3f..9eddb1a0e9 100644 }; /* The result of the creation of a chroot. */ -@@ -78,8 +80,11 @@ struct support_chroot +@@ -78,8 +85,11 @@ struct support_chroot /* Path to the chroot directory. */ char *path_chroot; @@ -11014,11 +11394,272 @@ index 859c2fda3f..9eddb1a0e9 100644 }; /* Create a chroot environment. The returned data should be freed +diff --git a/support/next_to_fault.c b/support/next_to_fault.c +new file mode 100644 +index 0000000000..7c6b077898 +--- /dev/null ++++ b/support/next_to_fault.c +@@ -0,0 +1,52 @@ ++/* Memory allocation next to an unmapped page. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/next_to_fault.h> ++#include <support/xunistd.h> ++#include <sys/mman.h> ++#include <sys/param.h> ++ ++struct support_next_to_fault ++support_next_to_fault_allocate (size_t size) ++{ ++ long page_size = sysconf (_SC_PAGE_SIZE); ++ TEST_VERIFY_EXIT (page_size > 0); ++ struct support_next_to_fault result; ++ result.region_size = roundup (size, page_size) + page_size; ++ if (size + page_size <= size || result.region_size <= size) ++ FAIL_EXIT1 ("support_next_to_fault_allocate (%zu): overflow", size); ++ result.region_start ++ = xmmap (NULL, result.region_size, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS, -1); ++ /* Unmap the page after the allocation. */ ++ xmprotect (result.region_start + (result.region_size - page_size), ++ page_size, PROT_NONE); ++ /* Align the allocation within the region so that it ends just ++ before the PROT_NONE page. */ ++ result.buffer = result.region_start + result.region_size - page_size - size; ++ result.length = size; ++ return result; ++} ++ ++void ++support_next_to_fault_free (struct support_next_to_fault *ntf) ++{ ++ xmunmap (ntf->region_start, ntf->region_size); ++ *ntf = (struct support_next_to_fault) { NULL, }; ++} +diff --git a/support/next_to_fault.h b/support/next_to_fault.h +new file mode 100644 +index 0000000000..dd71c28ac0 +--- /dev/null ++++ b/support/next_to_fault.h +@@ -0,0 +1,48 @@ ++/* Memory allocation next to an unmapped page. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#ifndef SUPPORT_NEXT_TO_FAULT_H ++#define SUPPORT_NEXT_TO_FAULT_H ++ ++#include <sys/cdefs.h> ++#include <sys/types.h> ++ ++__BEGIN_DECLS ++ ++/* The memory region created by next_to_fault_allocate. */ ++struct support_next_to_fault ++{ ++ /* The user data. */ ++ char *buffer; ++ size_t length; ++ ++ /* The entire allocated region. */ ++ void *region_start; ++ size_t region_size; ++}; ++ ++/* Allocate a buffer of SIZE bytes just before a page which is mapped ++ with PROT_NONE (so that overrunning the buffer will cause a ++ fault). */ ++struct support_next_to_fault support_next_to_fault_allocate (size_t size); ++ ++/* Deallocate the memory region allocated by ++ next_to_fault_allocate. */ ++void support_next_to_fault_free (struct support_next_to_fault *); ++ ++#endif /* SUPPORT_NEXT_TO_FAULT_H */ +diff --git a/support/support-xfstat.c b/support/support-xfstat.c +new file mode 100644 +index 0000000000..4c8ee9142b +--- /dev/null ++++ b/support/support-xfstat.c +@@ -0,0 +1,28 @@ ++/* fstat64 with error checking. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/xunistd.h> ++#include <sys/stat.h> ++ ++void ++xfstat (int fd, struct stat64 *result) ++{ ++ if (fstat64 (fd, result) != 0) ++ FAIL_EXIT1 ("fstat64 (%d): %m", fd); ++} +diff --git a/support/support.h b/support/support.h +index 4b5f04c2cc..bbba803ba1 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -68,6 +68,7 @@ void *xrealloc (void *p, size_t n); + char *xasprintf (const char *format, ...) + __attribute__ ((format (printf, 1, 2), malloc)); + char *xstrdup (const char *); ++char *xstrndup (const char *, size_t); + + __END_DECLS + +diff --git a/support/support_become_root.c b/support/support_become_root.c +index 3fa0bd4ac0..933138f99f 100644 +--- a/support/support_become_root.c ++++ b/support/support_become_root.c +@@ -18,18 +18,80 @@ + + #include <support/namespace.h> + ++#include <errno.h> ++#include <fcntl.h> + #include <sched.h> + #include <stdio.h> ++#include <string.h> ++#include <support/check.h> ++#include <support/xunistd.h> + #include <unistd.h> + ++#ifdef CLONE_NEWUSER ++/* The necessary steps to allow file creation in user namespaces. */ ++static void ++setup_uid_gid_mapping (uid_t original_uid, gid_t original_gid) ++{ ++ int fd = open64 ("/proc/self/uid_map", O_WRONLY); ++ if (fd < 0) ++ { ++ printf ("warning: could not open /proc/self/uid_map: %m\n" ++ "warning: file creation may not be possible\n"); ++ return; ++ } ++ ++ /* We map our original UID to the same UID in the container so we ++ own our own files normally. Without that, file creation could ++ fail with EOVERFLOW (sic!). */ ++ char buf[100]; ++ int ret = snprintf (buf, sizeof (buf), "%llu %llu 1\n", ++ (unsigned long long) original_uid, ++ (unsigned long long) original_uid); ++ TEST_VERIFY_EXIT (ret < sizeof (buf)); ++ xwrite (fd, buf, ret); ++ xclose (fd); ++ ++ /* Linux 3.19 introduced the setgroups file. We need write "deny" to this ++ file otherwise writing to gid_map will fail with EPERM. */ ++ fd = open64 ("/proc/self/setgroups", O_WRONLY, 0); ++ if (fd < 0) ++ { ++ if (errno != ENOENT) ++ FAIL_EXIT1 ("open64 (\"/proc/self/setgroups\", 0x%x, 0%o): %m", ++ O_WRONLY, 0); ++ /* This kernel doesn't expose the setgroups file so simply move on. */ ++ } ++ else ++ { ++ xwrite (fd, "deny\n", strlen ("deny\n")); ++ xclose (fd); ++ } ++ ++ /* Now map our own GID, like we did for the user ID. */ ++ fd = xopen ("/proc/self/gid_map", O_WRONLY, 0); ++ ret = snprintf (buf, sizeof (buf), "%llu %llu 1\n", ++ (unsigned long long) original_gid, ++ (unsigned long long) original_gid); ++ TEST_VERIFY_EXIT (ret < sizeof (buf)); ++ xwrite (fd, buf, ret); ++ xclose (fd); ++} ++#endif /* CLONE_NEWUSER */ ++ + bool + support_become_root (void) + { + #ifdef CLONE_NEWUSER ++ uid_t original_uid = getuid (); ++ gid_t original_gid = getgid (); ++ + if (unshare (CLONE_NEWUSER | CLONE_NEWNS) == 0) +- /* Even if we do not have UID zero, we have extended privileges at +- this point. */ +- return true; ++ { ++ setup_uid_gid_mapping (original_uid, original_gid); ++ /* Even if we do not have UID zero, we have extended privileges at ++ this point. */ ++ return true; ++ } + #endif + if (setuid (0) != 0) + { +diff --git a/support/support_can_chroot.c b/support/support_can_chroot.c +index 0dfd2deb54..a462753f76 100644 +--- a/support/support_can_chroot.c ++++ b/support/support_can_chroot.c +@@ -21,9 +21,9 @@ + #include <support/check.h> + #include <support/namespace.h> + #include <support/support.h> ++#include <support/xunistd.h> + #include <sys/stat.h> + #include <unistd.h> +-#include <xunistd.h> + + static void + callback (void *closure) diff --git a/support/support_chroot.c b/support/support_chroot.c -index c0807b313a..f3ef551b05 100644 +index c0807b313a..693813f694 100644 --- a/support/support_chroot.c +++ b/support/support_chroot.c -@@ -24,6 +24,23 @@ +@@ -24,30 +24,38 @@ #include <support/test-driver.h> #include <support/xunistd.h> @@ -11042,7 +11683,16 @@ index c0807b313a..f3ef551b05 100644 struct support_chroot * support_chroot_create (struct support_chroot_configuration conf) { -@@ -39,15 +56,10 @@ support_chroot_create (struct support_chroot_configuration conf) + struct support_chroot *chroot = xmalloc (sizeof (*chroot)); +- +- chroot->path_chroot = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir); +- if (mkdtemp (chroot->path_chroot) == NULL) +- FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", chroot->path_chroot); +- add_temp_file (chroot->path_chroot); ++ chroot->path_chroot = support_create_temp_directory ("tst-resolv-res_init-"); + + /* Create the /etc directory in the chroot environment. */ + char *path_etc = xasprintf ("%s/etc", chroot->path_chroot); xmkdir (path_etc, 0777); add_temp_file (path_etc); @@ -11062,7 +11712,7 @@ index c0807b313a..f3ef551b05 100644 free (path_etc); -@@ -67,5 +79,7 @@ support_chroot_free (struct support_chroot *chroot) +@@ -67,5 +75,7 @@ support_chroot_free (struct support_chroot *chroot) { free (chroot->path_chroot); free (chroot->path_resolv_conf); @@ -11070,70 +11720,14 @@ index c0807b313a..f3ef551b05 100644 + free (chroot->path_host_conf); free (chroot); } -diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile -index 78d52c717d..9aa1e79a80 100644 ---- a/sysdeps/aarch64/multiarch/Makefile -+++ b/sysdeps/aarch64/multiarch/Makefile -@@ -1,3 +1,4 @@ - ifeq ($(subdir),string) --sysdep_routines += memcpy_generic memcpy_thunderx -+sysdep_routines += memcpy_generic memcpy_thunderx memcpy_falkor \ -+ memmove_falkor - endif -diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c -index 32056bcec3..2cb74d5b43 100644 ---- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c -@@ -25,7 +25,7 @@ - #include <stdio.h> - - /* Maximum number of IFUNC implementations. */ --#define MAX_IFUNC 2 -+#define MAX_IFUNC 3 - - size_t - __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, -@@ -40,9 +40,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - /* Support sysdeps/aarch64/multiarch/memcpy.c and memmove.c. */ - IFUNC_IMPL (i, name, memcpy, - IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx) -+ IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_falkor) - IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_generic)) - IFUNC_IMPL (i, name, memmove, - IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx) -+ IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_falkor) - IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_generic)) - - return i; -diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c -index 9f73efbba7..b395df1c63 100644 ---- a/sysdeps/aarch64/multiarch/memcpy.c -+++ b/sysdeps/aarch64/multiarch/memcpy.c -@@ -30,9 +30,14 @@ extern __typeof (__redirect_memcpy) __libc_memcpy; - - extern __typeof (__redirect_memcpy) __memcpy_generic attribute_hidden; - extern __typeof (__redirect_memcpy) __memcpy_thunderx attribute_hidden; -+extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden; - - libc_ifunc (__libc_memcpy, -- IS_THUNDERX (midr) ? __memcpy_thunderx : __memcpy_generic); -+ (IS_THUNDERX (midr) -+ ? __memcpy_thunderx -+ : (IS_FALKOR (midr) -+ ? __memcpy_falkor -+ : __memcpy_generic))); - - # undef memcpy - strong_alias (__libc_memcpy, memcpy); -diff --git a/sysdeps/aarch64/multiarch/memcpy_falkor.S b/sysdeps/aarch64/multiarch/memcpy_falkor.S +diff --git a/support/support_enter_mount_namespace.c b/support/support_enter_mount_namespace.c new file mode 100644 -index 0000000000..dea4f225ee +index 0000000000..6140692075 --- /dev/null -+++ b/sysdeps/aarch64/multiarch/memcpy_falkor.S -@@ -0,0 +1,184 @@ -+/* Optimized memcpy for Qualcomm Falkor processor. ++++ b/support/support_enter_mount_namespace.c +@@ -0,0 +1,45 @@ ++/* Enter a mount namespace. + Copyright (C) 2017 Free Software Foundation, Inc. -+ + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or @@ -11147,202 +11741,228 @@ index 0000000000..dea4f225ee + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see ++ License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + -+#include <sysdep.h> -+ -+/* Assumptions: ++#include <support/namespace.h> + -+ ARMv8-a, AArch64, falkor, unaligned accesses. */ ++#include <sched.h> ++#include <stdio.h> ++#include <sys/mount.h> + -+#define dstin x0 -+#define src x1 -+#define count x2 -+#define dst x3 -+#define srcend x4 -+#define dstend x5 -+#define A_l x6 -+#define A_lw w6 -+#define A_h x7 -+#define A_hw w7 -+#define tmp1 x14 -+ -+/* Copies are split into 3 main cases: -+ -+ 1. Small copies of up to 32 bytes -+ 2. Medium copies of 33..128 bytes which are fully unrolled -+ 3. Large copies of more than 128 bytes. -+ -+ Large copies align the sourceto a quad word and use an unrolled loop -+ processing 64 bytes per iteration. -+ -+ FALKOR-SPECIFIC DESIGN: -+ -+ The smallest copies (32 bytes or less) focus on optimal pipeline usage, -+ which is why the redundant copies of 0-3 bytes have been replaced with -+ conditionals, since the former would unnecessarily break across multiple -+ issue groups. The medium copy group has been enlarged to 128 bytes since -+ bumping up the small copies up to 32 bytes allows us to do that without -+ cost and also allows us to reduce the size of the prep code before loop64. -+ -+ All copies are done only via two registers r6 and r7. This is to ensure -+ that all loads hit a single hardware prefetcher which can get correctly -+ trained to prefetch a single stream. -+ -+ The non-temporal stores help optimize cache utilization. */ -+ -+#if IS_IN (libc) -+ENTRY_ALIGN (__memcpy_falkor, 6) -+ -+ cmp count, 32 -+ add srcend, src, count -+ add dstend, dstin, count -+ b.ls L(copy32) -+ ldp A_l, A_h, [src] -+ cmp count, 128 -+ stp A_l, A_h, [dstin] -+ b.hi L(copy_long) ++bool ++support_enter_mount_namespace (void) ++{ ++#ifdef CLONE_NEWNS ++ if (unshare (CLONE_NEWNS) == 0) ++ { ++ /* On some systems, / is marked as MS_SHARED, which means that ++ mounts within the namespace leak to the rest of the system, ++ which is not what we want. */ ++ if (mount ("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0) ++ { ++ printf ("warning: making the mount namespace private failed: %m\n"); ++ return false; ++ } ++ return true; ++ } ++ else ++ printf ("warning: unshare (CLONE_NEWNS) failed: %m\n"); ++#endif /* CLONE_NEWNS */ ++ return false; ++} +diff --git a/support/support_format_addrinfo.c b/support/support_format_addrinfo.c +index eedb030591..daf335f775 100644 +--- a/support/support_format_addrinfo.c ++++ b/support/support_format_addrinfo.c +@@ -21,6 +21,7 @@ + #include <arpa/inet.h> + #include <errno.h> + #include <stdio.h> ++#include <stdlib.h> + #include <support/support.h> + #include <support/xmemstream.h> + +diff --git a/support/support_format_dns_packet.c b/support/support_format_dns_packet.c +index 2992c57971..e5ef1aa4b3 100644 +--- a/support/support_format_dns_packet.c ++++ b/support/support_format_dns_packet.c +@@ -20,6 +20,7 @@ + + #include <arpa/inet.h> + #include <resolv.h> ++#include <stdbool.h> + #include <support/check.h> + #include <support/support.h> + #include <support/xmemstream.h> +diff --git a/support/support_format_hostent.c b/support/support_format_hostent.c +index 5b5f26082e..0aac17972b 100644 +--- a/support/support_format_hostent.c ++++ b/support/support_format_hostent.c +@@ -19,7 +19,9 @@ + #include <support/format_nss.h> + + #include <arpa/inet.h> ++#include <errno.h> + #include <stdio.h> ++#include <stdlib.h> + #include <support/support.h> + #include <support/xmemstream.h> + +@@ -41,10 +43,15 @@ support_format_hostent (struct hostent *h) + { + if (h == NULL) + { +- char *value = support_format_herrno (h_errno); +- char *result = xasprintf ("error: %s\n", value); +- free (value); +- return result; ++ if (h_errno == NETDB_INTERNAL) ++ return xasprintf ("error: NETDB_INTERNAL (errno %d, %m)\n", errno); ++ else ++ { ++ char *value = support_format_herrno (h_errno); ++ char *result = xasprintf ("error: %s\n", value); ++ free (value); ++ return result; ++ } + } + + struct xmemstream mem; +diff --git a/support/support_format_netent.c b/support/support_format_netent.c +index 020f5720d9..be8f1720a2 100644 +--- a/support/support_format_netent.c ++++ b/support/support_format_netent.c +@@ -20,6 +20,7 @@ + + #include <arpa/inet.h> + #include <stdio.h> ++#include <stdlib.h> + #include <support/support.h> + #include <support/xmemstream.h> + +diff --git a/support/support_test_compare_failure.c b/support/support_test_compare_failure.c +new file mode 100644 +index 0000000000..894145b56d +--- /dev/null ++++ b/support/support_test_compare_failure.c +@@ -0,0 +1,55 @@ ++/* Reporting a numeric comparison failure. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. + -+ /* Medium copies: 33..128 bytes. */ -+ sub tmp1, count, 1 -+ ldp A_l, A_h, [src, 16] -+ stp A_l, A_h, [dstin, 16] -+ tbz tmp1, 6, 1f -+ ldp A_l, A_h, [src, 32] -+ stp A_l, A_h, [dstin, 32] -+ ldp A_l, A_h, [src, 48] -+ stp A_l, A_h, [dstin, 48] -+ ldp A_l, A_h, [srcend, -64] -+ stp A_l, A_h, [dstend, -64] -+ ldp A_l, A_h, [srcend, -48] -+ stp A_l, A_h, [dstend, -48] -+1: -+ ldp A_l, A_h, [srcend, -32] -+ stp A_l, A_h, [dstend, -32] -+ ldp A_l, A_h, [srcend, -16] -+ stp A_l, A_h, [dstend, -16] -+ ret ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. + -+ .p2align 4 -+ /* Small copies: 0..32 bytes. */ -+L(copy32): -+ /* 16-32 */ -+ cmp count, 16 -+ b.lo 1f -+ ldp A_l, A_h, [src] -+ stp A_l, A_h, [dstin] -+ ldp A_l, A_h, [srcend, -16] -+ stp A_l, A_h, [dstend, -16] -+ ret -+ .p2align 4 -+1: -+ /* 8-15 */ -+ tbz count, 3, 1f -+ ldr A_l, [src] -+ str A_l, [dstin] -+ ldr A_l, [srcend, -8] -+ str A_l, [dstend, -8] -+ ret -+ .p2align 4 -+1: -+ /* 4-7 */ -+ tbz count, 2, 1f -+ ldr A_lw, [src] -+ str A_lw, [dstin] -+ ldr A_lw, [srcend, -4] -+ str A_lw, [dstend, -4] -+ ret -+ .p2align 4 -+1: -+ /* 2-3 */ -+ tbz count, 1, 1f -+ ldrh A_lw, [src] -+ strh A_lw, [dstin] -+ ldrh A_lw, [srcend, -2] -+ strh A_lw, [dstend, -2] -+ ret -+ .p2align 4 -+1: -+ /* 0-1 */ -+ tbz count, 0, 1f -+ ldrb A_lw, [src] -+ strb A_lw, [dstin] -+1: -+ ret ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. + -+ /* Align SRC to 16 bytes and copy; that way at least one of the -+ accesses is aligned throughout the copy sequence. ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ + -+ The count is off by 0 to 15 bytes, but this is OK because we trim -+ off the last 64 bytes to copy off from the end. Due to this the -+ loop never runs out of bounds. */ -+ .p2align 6 -+L(copy_long): -+ sub count, count, 64 + 16 -+ and tmp1, src, 15 -+ bic src, src, 15 -+ sub dst, dstin, tmp1 -+ add count, count, tmp1 ++#include <stdio.h> ++#include <support/check.h> + -+L(loop64): -+ ldp A_l, A_h, [src, 16]! -+ stnp A_l, A_h, [dst, 16] -+ ldp A_l, A_h, [src, 16]! -+ subs count, count, 64 -+ stnp A_l, A_h, [dst, 32] -+ ldp A_l, A_h, [src, 16]! -+ stnp A_l, A_h, [dst, 48] -+ ldp A_l, A_h, [src, 16]! -+ stnp A_l, A_h, [dst, 64] -+ add dst, dst, 64 -+ b.hi L(loop64) ++static void ++report (const char *which, const char *expr, long long value, int negative, ++ int size) ++{ ++ printf (" %s: ", which); ++ if (negative) ++ printf ("%lld", value); ++ else ++ printf ("%llu", (unsigned long long) value); ++ unsigned long long mask ++ = (~0ULL) >> (8 * (sizeof (unsigned long long) - size)); ++ printf (" (0x%llx); from: %s\n", (unsigned long long) value & mask, expr); ++} + -+ /* Write the last full set of 64 bytes. The remainder is at most 64 -+ bytes, so it is safe to always copy 64 bytes from the end even if -+ there is just 1 byte left. */ -+L(last64): -+ ldp A_l, A_h, [srcend, -64] -+ stnp A_l, A_h, [dstend, -64] -+ ldp A_l, A_h, [srcend, -48] -+ stnp A_l, A_h, [dstend, -48] -+ ldp A_l, A_h, [srcend, -32] -+ stnp A_l, A_h, [dstend, -32] -+ ldp A_l, A_h, [srcend, -16] -+ stnp A_l, A_h, [dstend, -16] -+ ret ++void ++support_test_compare_failure (const char *file, int line, ++ const char *left_expr, ++ long long left_value, ++ int left_negative, ++ int left_size, ++ const char *right_expr, ++ long long right_value, ++ int right_negative, ++ int right_size) ++{ ++ support_record_failure (); ++ if (left_size != right_size) ++ printf ("%s:%d: numeric comparison failure (widths %d and %d)\n", ++ file, line, left_size * 8, right_size * 8); ++ else ++ printf ("%s:%d: numeric comparison failure\n", file, line); ++ report (" left", left_expr, left_value, left_negative, left_size); ++ report ("right", right_expr, right_value, right_negative, right_size); ++} +diff --git a/support/support_write_file_string.c b/support/support_write_file_string.c +index 48e89597f3..48736530bf 100644 +--- a/support/support_write_file_string.c ++++ b/support/support_write_file_string.c +@@ -19,7 +19,7 @@ + #include <fcntl.h> + #include <string.h> + #include <support/check.h> +-#include <xunistd.h> ++#include <support/xunistd.h> + + void + support_write_file_string (const char *path, const char *contents) +diff --git a/support/temp_file.c b/support/temp_file.c +index fdb2477ab9..547263a3e4 100644 +--- a/support/temp_file.c ++++ b/support/temp_file.c +@@ -86,6 +86,19 @@ create_temp_file (const char *base, char **filename) + return fd; + } + ++char * ++support_create_temp_directory (const char *base) ++{ ++ char *path = xasprintf ("%s/%sXXXXXX", test_dir, base); ++ if (mkdtemp (path) == NULL) ++ { ++ printf ("error: mkdtemp (\"%s\"): %m", path); ++ exit (1); ++ } ++ add_temp_file (path); ++ return path; ++} + -+END (__memcpy_falkor) -+libc_hidden_builtin_def (__memcpy_falkor) -+#endif -diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c -index 34c6b29bd5..016f03ee50 100644 ---- a/sysdeps/aarch64/multiarch/memmove.c -+++ b/sysdeps/aarch64/multiarch/memmove.c -@@ -30,9 +30,14 @@ extern __typeof (__redirect_memmove) __libc_memmove; + /* Helper functions called by the test skeleton follow. */ - extern __typeof (__redirect_memmove) __memmove_generic attribute_hidden; - extern __typeof (__redirect_memmove) __memmove_thunderx attribute_hidden; -+extern __typeof (__redirect_memmove) __memmove_falkor attribute_hidden; + void +diff --git a/support/temp_file.h b/support/temp_file.h +index 6fed8df1ea..3b8563e115 100644 +--- a/support/temp_file.h ++++ b/support/temp_file.h +@@ -32,6 +32,11 @@ void add_temp_file (const char *name); + *FILENAME. */ + int create_temp_file (const char *base, char **filename); - libc_ifunc (__libc_memmove, -- IS_THUNDERX (midr) ? __memmove_thunderx : __memmove_generic); -+ (IS_THUNDERX (midr) -+ ? __memmove_thunderx -+ : (IS_FALKOR (midr) -+ ? __memmove_falkor -+ : __memmove_generic))); ++/* Create a temporary directory and schedule it for deletion. BASE is ++ used as a prefix for the unique directory name, which the function ++ returns. The caller should free this string. */ ++char *support_create_temp_directory (const char *base); ++ + __END_DECLS - # undef memmove - strong_alias (__libc_memmove, memmove); -diff --git a/sysdeps/aarch64/multiarch/memmove_falkor.S b/sysdeps/aarch64/multiarch/memmove_falkor.S + #endif /* SUPPORT_TEMP_FILE_H */ +diff --git a/support/tst-test_compare.c b/support/tst-test_compare.c new file mode 100644 -index 0000000000..3a4e6a2a8e +index 0000000000..de138d4f8a --- /dev/null -+++ b/sysdeps/aarch64/multiarch/memmove_falkor.S -@@ -0,0 +1,232 @@ -+/* Copyright (C) 2017 Free Software Foundation, Inc. -+ ++++ b/support/tst-test_compare.c +@@ -0,0 +1,98 @@ ++/* Basic test for the TEST_COMPARE macro. ++ Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or @@ -11356,21 +11976,944 @@ index 0000000000..3a4e6a2a8e + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see ++ License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + -+#include <sysdep.h> ++#include <string.h> ++#include <support/check.h> ++#include <support/capture_subprocess.h> + -+/* Assumptions: ARMv8-a, AArch64, falkor, unaligned accesses. */ ++static void ++subprocess (void *closure) ++{ ++ char ch = 1; ++ /* These tests should fail. */ ++ TEST_COMPARE (ch, -1); /* Line 28. */ ++ TEST_COMPARE (2LL, -2LL); /* Line 29. */ ++ TEST_COMPARE (3LL, (short) -3); /* Line 30. */ ++} + -+#define dstin x0 -+#define src x1 -+#define count x2 -+#define dstlen x3 -+#define dst x3 -+#define srcend x4 -+#define dstend x5 -+#define A_l x6 ++struct bitfield ++{ ++ int i2 : 2; ++ int i3 : 3; ++ unsigned int u2 : 2; ++ unsigned int u3 : 3; ++ int i31 : 31; ++ unsigned int u31 : 31 ; ++ long long int i63 : 63; ++ unsigned long long int u63 : 63; ++}; ++ ++static int ++do_test (void) ++{ ++ /* This should succeed. */ ++ TEST_COMPARE (1, 1); ++ TEST_COMPARE (2LL, 2U); ++ { ++ char i8 = 3; ++ unsigned short u16 = 3; ++ TEST_COMPARE (i8, u16); ++ } ++ ++ struct bitfield bitfield = { 0 }; ++ TEST_COMPARE (bitfield.i2, bitfield.i3); ++ TEST_COMPARE (bitfield.u2, bitfield.u3); ++ TEST_COMPARE (bitfield.u2, bitfield.i3); ++ TEST_COMPARE (bitfield.u3, bitfield.i3); ++ TEST_COMPARE (bitfield.i2, bitfield.u3); ++ TEST_COMPARE (bitfield.i3, bitfield.u2); ++ TEST_COMPARE (bitfield.i63, bitfield.i63); ++ TEST_COMPARE (bitfield.u63, bitfield.u63); ++ TEST_COMPARE (bitfield.i31, bitfield.i63); ++ TEST_COMPARE (bitfield.i63, bitfield.i31); ++ ++ struct support_capture_subprocess proc = support_capture_subprocess ++ (&subprocess, NULL); ++ ++ /* Discard the reported error. */ ++ support_record_failure_reset (); ++ ++ puts ("info: *** subprocess output starts ***"); ++ fputs (proc.out.buffer, stdout); ++ puts ("info: *** subprocess output ends ***"); ++ ++ TEST_VERIFY ++ (strcmp (proc.out.buffer, ++ "tst-test_compare.c:28: numeric comparison failure\n" ++ " left: 1 (0x1); from: ch\n" ++ " right: -1 (0xffffffff); from: -1\n" ++ "tst-test_compare.c:29: numeric comparison failure\n" ++ " left: 2 (0x2); from: 2LL\n" ++ " right: -2 (0xfffffffffffffffe); from: -2LL\n" ++ "tst-test_compare.c:30: numeric comparison failure" ++ " (widths 64 and 32)\n" ++ " left: 3 (0x3); from: 3LL\n" ++ " right: -3 (0xfffffffd); from: (short) -3\n") == 0); ++ ++ /* Check that there is no output on standard error. */ ++ support_capture_subprocess_check (&proc, "TEST_COMPARE", 0, sc_allow_stdout); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/support/tst-xreadlink.c b/support/tst-xreadlink.c +new file mode 100644 +index 0000000000..a4a22812c1 +--- /dev/null ++++ b/support/tst-xreadlink.c +@@ -0,0 +1,72 @@ ++/* Test the xreadlink function. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <errno.h> ++#include <fcntl.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <support/check.h> ++#include <support/support.h> ++#include <support/temp_file.h> ++#include <support/xunistd.h> ++ ++static int ++do_test (void) ++{ ++ char *dir = support_create_temp_directory ("tst-xreadlink-"); ++ char *symlink_name = xasprintf ("%s/symlink", dir); ++ add_temp_file (symlink_name); ++ ++ /* The limit 10000 is arbitrary and simply there to prevent an ++ attempt to exhaust all available disk space. */ ++ for (int size = 1; size < 10000; ++size) ++ { ++ char *contents = xmalloc (size + 1); ++ for (int i = 0; i < size; ++i) ++ contents[i] = 'a' + (rand () % 26); ++ contents[size] = '\0'; ++ if (symlink (contents, symlink_name) != 0) ++ { ++ if (errno == ENAMETOOLONG) ++ { ++ printf ("info: ENAMETOOLONG failure at %d bytes\n", size); ++ free (contents); ++ break; ++ } ++ FAIL_EXIT1 ("symlink (%d bytes): %m", size); ++ } ++ ++ char *readlink_result = xreadlink (symlink_name); ++ TEST_VERIFY (strcmp (readlink_result, contents) == 0); ++ free (readlink_result); ++ xunlink (symlink_name); ++ free (contents); ++ } ++ ++ /* Create an empty file to suppress the temporary file deletion ++ warning. */ ++ xclose (xopen (symlink_name, O_WRONLY | O_CREAT, 0)); ++ ++ free (symlink_name); ++ free (dir); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/support/xdlfcn.c b/support/xdlfcn.c +new file mode 100644 +index 0000000000..05966c41ef +--- /dev/null ++++ b/support/xdlfcn.c +@@ -0,0 +1,59 @@ ++/* Support functionality for using dlopen/dlclose/dlsym. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <stddef.h> ++#include <support/check.h> ++#include <support/xdlfcn.h> ++ ++void * ++xdlopen (const char *filename, int flags) ++{ ++ void *dso = dlopen (filename, flags); ++ ++ if (dso == NULL) ++ FAIL_EXIT1 ("error: dlopen: %s\n", dlerror ()); ++ ++ /* Clear any errors. */ ++ dlerror (); ++ ++ return dso; ++} ++ ++void * ++xdlsym (void *handle, const char *symbol) ++{ ++ void *sym = dlsym (handle, symbol); ++ ++ if (sym == NULL) ++ FAIL_EXIT1 ("error: dlsym: %s\n", dlerror ()); ++ ++ /* Clear any errors. */ ++ dlerror (); ++ ++ return sym; ++} ++ ++void ++xdlclose (void *handle) ++{ ++ if (dlclose (handle) != 0) ++ FAIL_EXIT1 ("error: dlclose: %s\n", dlerror ()); ++ ++ /* Clear any errors. */ ++ dlerror (); ++} +diff --git a/support/xdlfcn.h b/support/xdlfcn.h +new file mode 100644 +index 0000000000..9bdcb38d3e +--- /dev/null ++++ b/support/xdlfcn.h +@@ -0,0 +1,34 @@ ++/* Support functionality for using dlopen/dlclose/dlsym. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#ifndef SUPPORT_DLOPEN_H ++#define SUPPORT_DLOPEN_H ++ ++#include <dlfcn.h> ++ ++__BEGIN_DECLS ++ ++/* Each of these terminates process on failure with relevant error message. */ ++void *xdlopen (const char *filename, int flags); ++void *xdlsym (void *handle, const char *symbol); ++void xdlclose (void *handle); ++ ++ ++__END_DECLS ++ ++#endif /* SUPPORT_DLOPEN_H */ +diff --git a/support/xftruncate.c b/support/xftruncate.c +new file mode 100644 +index 0000000000..9c4e9e3050 +--- /dev/null ++++ b/support/xftruncate.c +@@ -0,0 +1,27 @@ ++/* ftruncate with error checking. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/xunistd.h> ++ ++void ++xftruncate (int fd, long long length) ++{ ++ if (ftruncate64 (fd, length) != 0) ++ FAIL_EXIT1 ("ftruncate64 (%d, %lld): %m", fd, length); ++} +diff --git a/support/xlseek.c b/support/xlseek.c +new file mode 100644 +index 0000000000..0a75a9f2e6 +--- /dev/null ++++ b/support/xlseek.c +@@ -0,0 +1,29 @@ ++/* lseek with error checking. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/xunistd.h> ++ ++long long ++xlseek (int fd, long long offset, int whence) ++{ ++ long long result = lseek64 (fd, offset, whence); ++ if (result < 0) ++ FAIL_EXIT1 ("lseek64 (%d, %lld, %d): %m", fd, offset, whence); ++ return result; ++} +diff --git a/support/xraise.c b/support/xraise.c +new file mode 100644 +index 0000000000..9126c6c3ea +--- /dev/null ++++ b/support/xraise.c +@@ -0,0 +1,27 @@ ++/* Error-checking wrapper for raise. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/xsignal.h> ++ ++void ++xraise (int sig) ++{ ++ if (raise (sig) != 0) ++ FAIL_EXIT1 ("raise (%d): %m" , sig); ++} +diff --git a/support/xreadlink.c b/support/xreadlink.c +new file mode 100644 +index 0000000000..aec58a2aa6 +--- /dev/null ++++ b/support/xreadlink.c +@@ -0,0 +1,44 @@ ++/* Error-checking, allocating wrapper for readlink. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <scratch_buffer.h> ++#include <support/check.h> ++#include <support/support.h> ++#include <xunistd.h> ++ ++char * ++xreadlink (const char *path) ++{ ++ struct scratch_buffer buf; ++ scratch_buffer_init (&buf); ++ ++ while (true) ++ { ++ ssize_t count = readlink (path, buf.data, buf.length); ++ if (count < 0) ++ FAIL_EXIT1 ("readlink (\"%s\"): %m", path); ++ if (count < buf.length) ++ { ++ char *result = xstrndup (buf.data, count); ++ scratch_buffer_free (&buf); ++ return result; ++ } ++ if (!scratch_buffer_grow (&buf)) ++ FAIL_EXIT1 ("scratch_buffer_grow in xreadlink"); ++ } ++} +diff --git a/support/xsigaction.c b/support/xsigaction.c +new file mode 100644 +index 0000000000..b74c69afae +--- /dev/null ++++ b/support/xsigaction.c +@@ -0,0 +1,27 @@ ++/* Error-checking wrapper for sigaction. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/xsignal.h> ++ ++void ++xsigaction (int sig, const struct sigaction *newact, struct sigaction *oldact) ++{ ++ if (sigaction (sig, newact, oldact)) ++ FAIL_EXIT1 ("sigaction (%d): %m" , sig); ++} +diff --git a/support/xsignal.c b/support/xsignal.c +new file mode 100644 +index 0000000000..22a1dd74a7 +--- /dev/null ++++ b/support/xsignal.c +@@ -0,0 +1,29 @@ ++/* Error-checking wrapper for signal. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/xsignal.h> ++ ++sighandler_t ++xsignal (int sig, sighandler_t handler) ++{ ++ sighandler_t result = signal (sig, handler); ++ if (result == SIG_ERR) ++ FAIL_EXIT1 ("signal (%d, %p): %m", sig, handler); ++ return result; ++} +diff --git a/support/xsignal.h b/support/xsignal.h +index 3dc0d9d5ce..3087ed0082 100644 +--- a/support/xsignal.h ++++ b/support/xsignal.h +@@ -24,6 +24,14 @@ + + __BEGIN_DECLS + ++/* The following functions call the corresponding libc functions and ++ terminate the process on error. */ ++ ++void xraise (int sig); ++sighandler_t xsignal (int sig, sighandler_t handler); ++void xsigaction (int sig, const struct sigaction *newact, ++ struct sigaction *oldact); ++ + /* The following functions call the corresponding libpthread functions + and terminate the process on error. */ + +diff --git a/support/xstrndup.c b/support/xstrndup.c +new file mode 100644 +index 0000000000..d59a283d25 +--- /dev/null ++++ b/support/xstrndup.c +@@ -0,0 +1,30 @@ ++/* strndup with error checking. ++ Copyright (C) 2016-2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/support.h> ++ ++#include <string.h> ++ ++char * ++xstrndup (const char *s, size_t length) ++{ ++ char *p = strndup (s, length); ++ if (p == NULL) ++ oom_error ("strndup", length); ++ return p; ++} +diff --git a/support/xsysconf.c b/support/xsysconf.c +new file mode 100644 +index 0000000000..15ab1e26c4 +--- /dev/null ++++ b/support/xsysconf.c +@@ -0,0 +1,36 @@ ++/* Error-checking wrapper for sysconf. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <errno.h> ++#include <support/check.h> ++#include <support/xunistd.h> ++ ++long ++xsysconf (int name) ++{ ++ /* Detect errors by a changed errno value, in case -1 is a valid ++ value. Make sure that the caller does not see the zero value for ++ errno. */ ++ int old_errno = errno; ++ errno = 0; ++ long result = sysconf (name); ++ if (errno != 0) ++ FAIL_EXIT1 ("sysconf (%d): %m", name); ++ errno = old_errno; ++ return result; ++} +diff --git a/support/xunistd.h b/support/xunistd.h +index c947bfd8fb..29da063c15 100644 +--- a/support/xunistd.h ++++ b/support/xunistd.h +@@ -36,8 +36,17 @@ void xpipe (int[2]); + void xdup2 (int, int); + int xopen (const char *path, int flags, mode_t); + void xstat (const char *path, struct stat64 *); ++void xfstat (int fd, struct stat64 *); + void xmkdir (const char *path, mode_t); + void xchroot (const char *path); ++void xunlink (const char *path); ++long xsysconf (int name); ++long long xlseek (int fd, long long offset, int whence); ++void xftruncate (int fd, long long length); ++ ++/* Read the link at PATH. The caller should free the returned string ++ with free. */ ++char *xreadlink (const char *path); + + /* Close the file descriptor. Ignore EINTR errors, but terminate the + process on other errors. */ +diff --git a/support/xunlink.c b/support/xunlink.c +new file mode 100644 +index 0000000000..f94ee118cf +--- /dev/null ++++ b/support/xunlink.c +@@ -0,0 +1,27 @@ ++/* Error-checking wrapper for unlink. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/xunistd.h> ++ ++void ++xunlink (const char *path) ++{ ++ if (unlink (path) != 0) ++ FAIL_EXIT1 ("unlink (\"%s\"): %m", path); ++} +diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile +index 78d52c717d..9aa1e79a80 100644 +--- a/sysdeps/aarch64/multiarch/Makefile ++++ b/sysdeps/aarch64/multiarch/Makefile +@@ -1,3 +1,4 @@ + ifeq ($(subdir),string) +-sysdep_routines += memcpy_generic memcpy_thunderx ++sysdep_routines += memcpy_generic memcpy_thunderx memcpy_falkor \ ++ memmove_falkor + endif +diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c +index 32056bcec3..2cb74d5b43 100644 +--- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c +@@ -25,7 +25,7 @@ + #include <stdio.h> + + /* Maximum number of IFUNC implementations. */ +-#define MAX_IFUNC 2 ++#define MAX_IFUNC 3 + + size_t + __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, +@@ -40,9 +40,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/aarch64/multiarch/memcpy.c and memmove.c. */ + IFUNC_IMPL (i, name, memcpy, + IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx) ++ IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_falkor) + IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_generic)) + IFUNC_IMPL (i, name, memmove, + IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx) ++ IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_falkor) + IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_generic)) + + return i; +diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c +index 9f73efbba7..b395df1c63 100644 +--- a/sysdeps/aarch64/multiarch/memcpy.c ++++ b/sysdeps/aarch64/multiarch/memcpy.c +@@ -30,9 +30,14 @@ extern __typeof (__redirect_memcpy) __libc_memcpy; + + extern __typeof (__redirect_memcpy) __memcpy_generic attribute_hidden; + extern __typeof (__redirect_memcpy) __memcpy_thunderx attribute_hidden; ++extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden; + + libc_ifunc (__libc_memcpy, +- IS_THUNDERX (midr) ? __memcpy_thunderx : __memcpy_generic); ++ (IS_THUNDERX (midr) ++ ? __memcpy_thunderx ++ : (IS_FALKOR (midr) ++ ? __memcpy_falkor ++ : __memcpy_generic))); + + # undef memcpy + strong_alias (__libc_memcpy, memcpy); +diff --git a/sysdeps/aarch64/multiarch/memcpy_falkor.S b/sysdeps/aarch64/multiarch/memcpy_falkor.S +new file mode 100644 +index 0000000000..dea4f225ee +--- /dev/null ++++ b/sysdeps/aarch64/multiarch/memcpy_falkor.S +@@ -0,0 +1,184 @@ ++/* Optimized memcpy for Qualcomm Falkor processor. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <sysdep.h> ++ ++/* Assumptions: ++ ++ ARMv8-a, AArch64, falkor, unaligned accesses. */ ++ ++#define dstin x0 ++#define src x1 ++#define count x2 ++#define dst x3 ++#define srcend x4 ++#define dstend x5 ++#define A_l x6 ++#define A_lw w6 ++#define A_h x7 ++#define A_hw w7 ++#define tmp1 x14 ++ ++/* Copies are split into 3 main cases: ++ ++ 1. Small copies of up to 32 bytes ++ 2. Medium copies of 33..128 bytes which are fully unrolled ++ 3. Large copies of more than 128 bytes. ++ ++ Large copies align the sourceto a quad word and use an unrolled loop ++ processing 64 bytes per iteration. ++ ++ FALKOR-SPECIFIC DESIGN: ++ ++ The smallest copies (32 bytes or less) focus on optimal pipeline usage, ++ which is why the redundant copies of 0-3 bytes have been replaced with ++ conditionals, since the former would unnecessarily break across multiple ++ issue groups. The medium copy group has been enlarged to 128 bytes since ++ bumping up the small copies up to 32 bytes allows us to do that without ++ cost and also allows us to reduce the size of the prep code before loop64. ++ ++ All copies are done only via two registers r6 and r7. This is to ensure ++ that all loads hit a single hardware prefetcher which can get correctly ++ trained to prefetch a single stream. ++ ++ The non-temporal stores help optimize cache utilization. */ ++ ++#if IS_IN (libc) ++ENTRY_ALIGN (__memcpy_falkor, 6) ++ ++ cmp count, 32 ++ add srcend, src, count ++ add dstend, dstin, count ++ b.ls L(copy32) ++ ldp A_l, A_h, [src] ++ cmp count, 128 ++ stp A_l, A_h, [dstin] ++ b.hi L(copy_long) ++ ++ /* Medium copies: 33..128 bytes. */ ++ sub tmp1, count, 1 ++ ldp A_l, A_h, [src, 16] ++ stp A_l, A_h, [dstin, 16] ++ tbz tmp1, 6, 1f ++ ldp A_l, A_h, [src, 32] ++ stp A_l, A_h, [dstin, 32] ++ ldp A_l, A_h, [src, 48] ++ stp A_l, A_h, [dstin, 48] ++ ldp A_l, A_h, [srcend, -64] ++ stp A_l, A_h, [dstend, -64] ++ ldp A_l, A_h, [srcend, -48] ++ stp A_l, A_h, [dstend, -48] ++1: ++ ldp A_l, A_h, [srcend, -32] ++ stp A_l, A_h, [dstend, -32] ++ ldp A_l, A_h, [srcend, -16] ++ stp A_l, A_h, [dstend, -16] ++ ret ++ ++ .p2align 4 ++ /* Small copies: 0..32 bytes. */ ++L(copy32): ++ /* 16-32 */ ++ cmp count, 16 ++ b.lo 1f ++ ldp A_l, A_h, [src] ++ stp A_l, A_h, [dstin] ++ ldp A_l, A_h, [srcend, -16] ++ stp A_l, A_h, [dstend, -16] ++ ret ++ .p2align 4 ++1: ++ /* 8-15 */ ++ tbz count, 3, 1f ++ ldr A_l, [src] ++ str A_l, [dstin] ++ ldr A_l, [srcend, -8] ++ str A_l, [dstend, -8] ++ ret ++ .p2align 4 ++1: ++ /* 4-7 */ ++ tbz count, 2, 1f ++ ldr A_lw, [src] ++ str A_lw, [dstin] ++ ldr A_lw, [srcend, -4] ++ str A_lw, [dstend, -4] ++ ret ++ .p2align 4 ++1: ++ /* 2-3 */ ++ tbz count, 1, 1f ++ ldrh A_lw, [src] ++ strh A_lw, [dstin] ++ ldrh A_lw, [srcend, -2] ++ strh A_lw, [dstend, -2] ++ ret ++ .p2align 4 ++1: ++ /* 0-1 */ ++ tbz count, 0, 1f ++ ldrb A_lw, [src] ++ strb A_lw, [dstin] ++1: ++ ret ++ ++ /* Align SRC to 16 bytes and copy; that way at least one of the ++ accesses is aligned throughout the copy sequence. ++ ++ The count is off by 0 to 15 bytes, but this is OK because we trim ++ off the last 64 bytes to copy off from the end. Due to this the ++ loop never runs out of bounds. */ ++ .p2align 6 ++L(copy_long): ++ sub count, count, 64 + 16 ++ and tmp1, src, 15 ++ bic src, src, 15 ++ sub dst, dstin, tmp1 ++ add count, count, tmp1 ++ ++L(loop64): ++ ldp A_l, A_h, [src, 16]! ++ stnp A_l, A_h, [dst, 16] ++ ldp A_l, A_h, [src, 16]! ++ subs count, count, 64 ++ stnp A_l, A_h, [dst, 32] ++ ldp A_l, A_h, [src, 16]! ++ stnp A_l, A_h, [dst, 48] ++ ldp A_l, A_h, [src, 16]! ++ stnp A_l, A_h, [dst, 64] ++ add dst, dst, 64 ++ b.hi L(loop64) ++ ++ /* Write the last full set of 64 bytes. The remainder is at most 64 ++ bytes, so it is safe to always copy 64 bytes from the end even if ++ there is just 1 byte left. */ ++L(last64): ++ ldp A_l, A_h, [srcend, -64] ++ stnp A_l, A_h, [dstend, -64] ++ ldp A_l, A_h, [srcend, -48] ++ stnp A_l, A_h, [dstend, -48] ++ ldp A_l, A_h, [srcend, -32] ++ stnp A_l, A_h, [dstend, -32] ++ ldp A_l, A_h, [srcend, -16] ++ stnp A_l, A_h, [dstend, -16] ++ ret ++ ++END (__memcpy_falkor) ++libc_hidden_builtin_def (__memcpy_falkor) ++#endif +diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c +index 34c6b29bd5..016f03ee50 100644 +--- a/sysdeps/aarch64/multiarch/memmove.c ++++ b/sysdeps/aarch64/multiarch/memmove.c +@@ -30,9 +30,14 @@ extern __typeof (__redirect_memmove) __libc_memmove; + + extern __typeof (__redirect_memmove) __memmove_generic attribute_hidden; + extern __typeof (__redirect_memmove) __memmove_thunderx attribute_hidden; ++extern __typeof (__redirect_memmove) __memmove_falkor attribute_hidden; + + libc_ifunc (__libc_memmove, +- IS_THUNDERX (midr) ? __memmove_thunderx : __memmove_generic); ++ (IS_THUNDERX (midr) ++ ? __memmove_thunderx ++ : (IS_FALKOR (midr) ++ ? __memmove_falkor ++ : __memmove_generic))); + + # undef memmove + strong_alias (__libc_memmove, memmove); +diff --git a/sysdeps/aarch64/multiarch/memmove_falkor.S b/sysdeps/aarch64/multiarch/memmove_falkor.S +new file mode 100644 +index 0000000000..3a4e6a2a8e +--- /dev/null ++++ b/sysdeps/aarch64/multiarch/memmove_falkor.S +@@ -0,0 +1,232 @@ ++/* Copyright (C) 2017 Free Software Foundation, Inc. ++ ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <sysdep.h> ++ ++/* Assumptions: ARMv8-a, AArch64, falkor, unaligned accesses. */ ++ ++#define dstin x0 ++#define src x1 ++#define count x2 ++#define dstlen x3 ++#define dst x3 ++#define srcend x4 ++#define dstend x5 ++#define A_l x6 +#define A_lw w6 +#define A_h x7 +#define A_hw w7 @@ -19811,19 +21354,20 @@ index 0000000000..bdda1f197e +# define __PTHREAD_MUTEX_LIST_OFFSET 20 +#endif diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile -index 9d6a2de870..dbe6a36c57 100644 +index 9d6a2de870..b1fe960d00 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile -@@ -50,7 +50,7 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \ +@@ -50,7 +50,8 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \ bits/siginfo-arch.h bits/siginfo-consts-arch.h tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \ - tst-quota tst-sync_file_range test-errno-linux -+ tst-quota tst-sync_file_range test-errno-linux tst-sysconf-iov_max ++ tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \ ++ test-errno-linux # Generate the list of SYS_* macros for the system calls (__NR_* macros). -@@ -120,7 +120,11 @@ ifndef no_deps +@@ -120,7 +121,11 @@ ifndef no_deps -include $(objpfx)bits/syscall.d endif generated += bits/syscall.h bits/syscall.d @@ -19836,7 +21380,7 @@ index 9d6a2de870..dbe6a36c57 100644 ifeq ($(subdir),time) sysdep_headers += sys/timex.h bits/timex.h -@@ -162,7 +166,7 @@ endif +@@ -162,7 +167,7 @@ endif ifeq ($(subdir),posix) sysdep_headers += bits/initspin.h @@ -20707,17 +22251,147 @@ index 094e05124b..0000000000 -#endif diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h b/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h new file mode 100644 -index 0000000000..094e05124b +index 0000000000..094e05124b +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h +@@ -0,0 +1,26 @@ ++/* Properties of long double type. SPARC version. ++ Copyright (C) 2016-2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <bits/wordsize.h> ++ ++#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32 ++# define __LONG_DOUBLE_MATH_OPTIONAL 1 ++# ifndef __LONG_DOUBLE_128__ ++# define __NO_LONG_DOUBLE_MATH 1 ++# endif ++#endif +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c +deleted file mode 100644 +index 82a9a296a7..0000000000 +--- a/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c ++++ /dev/null +@@ -1 +0,0 @@ +-#include <sysdeps/unix/sysv/linux/i386/glob64.c> +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h b/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h +new file mode 100644 +index 0000000000..094e05124b +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h +@@ -0,0 +1,26 @@ ++/* Properties of long double type. SPARC version. ++ Copyright (C) 2016-2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <bits/wordsize.h> ++ ++#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32 ++# define __LONG_DOUBLE_MATH_OPTIONAL 1 ++# ifndef __LONG_DOUBLE_128__ ++# define __NO_LONG_DOUBLE_MATH 1 ++# endif ++#endif +diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c +index c56f894a82..7d23df84d2 100644 +--- a/sysdeps/unix/sysv/linux/spawni.c ++++ b/sysdeps/unix/sysv/linux/spawni.c +@@ -17,7 +17,6 @@ + <http://www.gnu.org/licenses/>. */ + + #include <spawn.h> +-#include <assert.h> + #include <fcntl.h> + #include <paths.h> + #include <string.h> +@@ -268,7 +267,6 @@ __spawni_child (void *arguments) + __sigprocmask (SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) + ? &attr->__ss : &args->oldmask, 0); + +- args->err = 0; + args->exec (args->file, args->argv, args->envp); + + /* This is compatibility function required to enable posix_spawn run +@@ -339,7 +337,7 @@ __spawnix (pid_t * pid, const char *file, + + /* Child must set args.err to something non-negative - we rely on + the parent and child sharing VM. */ +- args.err = -1; ++ args.err = 0; + args.file = file; + args.exec = exec; + args.fa = file_actions; +@@ -362,12 +360,26 @@ __spawnix (pid_t * pid, const char *file, + new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size, + CLONE_VM | CLONE_VFORK | SIGCHLD, &args); + ++ /* It needs to collect the case where the auxiliary process was created ++ but failed to execute the file (due either any preparation step or ++ for execve itself). */ + if (new_pid > 0) + { ++ /* Also, it handles the unlikely case where the auxiliary process was ++ terminated before calling execve as if it was successfully. The ++ args.err is set to 0 as default and changed to a positive value ++ only in case of failure, so in case of premature termination ++ due a signal args.err will remain zeroed and it will be up to ++ caller to actually collect it. */ + ec = args.err; +- assert (ec >= 0); +- if (ec != 0) +- __waitpid (new_pid, NULL, 0); ++ if (ec > 0) ++ /* There still an unlikely case where the child is cancelled after ++ setting args.err, due to a positive error value. Also there is ++ possible pid reuse race (where the kernel allocated the same pid ++ to an unrelated process). Unfortunately due synchronization ++ issues where the kernel might not have the process collected ++ the waitpid below can not use WNOHANG. */ ++ __waitpid (new_pid, NULL, 0); + } + else + ec = -new_pid; +diff --git a/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c +new file mode 100644 +index 0000000000..1240b846e6 --- /dev/null -+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h -@@ -0,0 +1,26 @@ -+/* Properties of long double type. SPARC version. -+ Copyright (C) 2016-2017 Free Software Foundation, Inc. ++++ b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c +@@ -0,0 +1,27 @@ ++/* Check IOV_MAX definition: Helper function to capture UAPI header value. ++ Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public -+ License published by the Free Software Foundation; either ++ License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, @@ -20729,191 +22403,930 @@ index 0000000000..094e05124b + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + -+#include <bits/wordsize.h> ++/* Use a separate function to avoid header compatibility issues. */ + -+#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32 -+# define __LONG_DOUBLE_MATH_OPTIONAL 1 -+# ifndef __LONG_DOUBLE_128__ -+# define __NO_LONG_DOUBLE_MATH 1 -+# endif -+#endif -diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c -deleted file mode 100644 -index 82a9a296a7..0000000000 ---- a/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c -+++ /dev/null -@@ -1 +0,0 @@ --#include <sysdeps/unix/sysv/linux/i386/glob64.c> -diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h b/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h ++#include <linux/uio.h> ++ ++long ++uio_maxiov_value (void) ++{ ++ return UIO_MAXIOV; ++} +diff --git a/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c new file mode 100644 -index 0000000000..094e05124b +index 0000000000..dfdf3da484 --- /dev/null -+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h -@@ -0,0 +1,26 @@ -+/* Properties of long double type. SPARC version. -+ Copyright (C) 2016-2017 Free Software Foundation, Inc. ++++ b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c +@@ -0,0 +1,40 @@ ++/* Check IOV_MAX definition for consistency (bug 22321). ++ Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public -+ License published by the Free Software Foundation; either ++ License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* Defined in tst-sysconf-iov_max-uapi.c. */ ++long uio_maxiov_value (void); ++ ++ ++#include <limits.h> ++#include <support/check.h> ++#include <sys/uio.h> ++#include <unistd.h> ++ ++static int ++do_test (void) ++{ ++ TEST_VERIFY (_XOPEN_IOV_MAX == 16); /* Value required by POSIX. */ ++ TEST_VERIFY (uio_maxiov_value () >= _XOPEN_IOV_MAX); ++ TEST_VERIFY (IOV_MAX == uio_maxiov_value ()); ++ TEST_VERIFY (UIO_MAXIOV == uio_maxiov_value ()); ++ TEST_VERIFY (sysconf (_SC_UIO_MAXIOV) == uio_maxiov_value ()); ++ TEST_VERIFY (sysconf (_SC_IOV_MAX) == uio_maxiov_value ()); ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/sysdeps/unix/sysv/linux/tst-ttyname.c b/sysdeps/unix/sysv/linux/tst-ttyname.c +new file mode 100644 +index 0000000000..0fdf1a8ccb +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-ttyname.c +@@ -0,0 +1,570 @@ ++/* Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If ++ not, see <http://www.gnu.org/licenses/>. */ ++ ++#include <dirent.h> ++#include <errno.h> ++#include <fcntl.h> ++#include <limits.h> ++#include <sched.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <sys/mount.h> ++#include <sys/prctl.h> ++#include <sys/stat.h> ++#include <sys/wait.h> ++#include <unistd.h> ++ ++#include <support/check.h> ++#include <support/namespace.h> ++#include <support/support.h> ++#include <support/temp_file.h> ++#include <support/test-driver.h> ++#include <support/xunistd.h> ++ ++/* generic utilities */ ++ ++#define VERIFY(expr) \ ++ do { \ ++ if (!(expr)) \ ++ { \ ++ printf ("error: %s:%d: %s: %m\n", \ ++ __FILE__, __LINE__, #expr); \ ++ exit (1); \ ++ } \ ++ } while (0) ++ ++static void ++touch (const char *path, mode_t mode) ++{ ++ xclose (xopen (path, O_WRONLY|O_CREAT|O_NOCTTY, mode)); ++} ++ ++static size_t ++trim_prefix (char *str, size_t str_len, const char *prefix) ++{ ++ size_t prefix_len = strlen (prefix); ++ if (str_len > prefix_len && memcmp (str, prefix, prefix_len) == 0) ++ { ++ memmove (str, str + prefix_len, str_len - prefix_len); ++ return str_len - prefix_len; ++ } ++ return str_len; ++} ++ ++/* returns a pointer to static storage */ ++static char * ++proc_fd_readlink (const char *linkname) ++{ ++ static char target[PATH_MAX+1]; ++ ssize_t target_len = readlink (linkname, target, PATH_MAX); ++ VERIFY (target_len > 0); ++ target_len = trim_prefix (target, target_len, "(unreachable)"); ++ target[target_len] = '\0'; ++ return target; ++} ++ ++/* plain ttyname runner */ ++ ++struct result ++{ ++ const char *name; ++ int err; ++}; ++ ++/* strings in result structure are in static storage */ ++static struct result ++run_ttyname (int fd) ++{ ++ struct result ret; ++ errno = 0; ++ ret.name = ttyname (fd); ++ ret.err = errno; ++ return ret; ++} ++ ++static bool ++eq_ttyname (struct result actual, struct result expected) ++{ ++ char *actual_name, *expected_name; ++ ++ if ((actual.err == expected.err) && ++ (!actual.name == !expected.name) && ++ (actual.name ? strcmp (actual.name, expected.name) == 0 : true)) ++ { ++ if (expected.name) ++ expected_name = xasprintf ("\"%s\"", expected.name); ++ else ++ expected_name = xstrdup ("NULL"); ++ ++ printf ("info: ttyname: PASS {name=%s, errno=%d}\n", ++ expected_name, expected.err); ++ ++ free (expected_name); ++ return true; ++ } ++ ++ if (actual.name) ++ actual_name = xasprintf ("\"%s\"", actual.name); ++ else ++ actual_name = xstrdup ("NULL"); ++ ++ if (expected.name) ++ expected_name = xasprintf ("\"%s\"", expected.name); ++ else ++ expected_name = xstrdup ("NULL"); ++ ++ printf ("error: ttyname: actual {name=%s, errno=%d} != expected {name=%s, errno=%d}\n", ++ actual_name, actual.err, ++ expected_name, expected.err); ++ ++ free (actual_name); ++ free (expected_name); ++ return false; ++} ++ ++/* ttyname_r runner */ ++ ++struct result_r ++{ ++ const char *name; ++ int ret; ++ int err; ++}; ++ ++/* strings in result structure are in static storage */ ++static struct result_r ++run_ttyname_r (int fd) ++{ ++ static char buf[TTY_NAME_MAX]; ++ ++ struct result_r ret; ++ errno = 0; ++ ret.ret = ttyname_r (fd, buf, TTY_NAME_MAX); ++ ret.err = errno; ++ if (ret.ret == 0) ++ ret.name = buf; ++ else ++ ret.name = NULL; ++ return ret; ++} ++ ++static bool ++eq_ttyname_r (struct result_r actual, struct result_r expected) ++{ ++ char *actual_name, *expected_name; ++ ++ if ((actual.err == expected.err) && ++ (actual.ret == expected.ret) && ++ (!actual.name == !expected.name) && ++ (actual.name ? strcmp (actual.name, expected.name) == 0 : true)) ++ { ++ if (expected.name) ++ expected_name = xasprintf ("\"%s\"", expected.name); ++ else ++ expected_name = xstrdup ("NULL"); ++ ++ printf ("info: ttyname_r: PASS {name=%s, ret=%d, errno=%d}\n", ++ expected_name, expected.ret, expected.err); ++ ++ free (expected_name); ++ return true; ++ } ++ ++ if (actual.name) ++ actual_name = xasprintf ("\"%s\"", actual.name); ++ else ++ actual_name = xstrdup ("NULL"); ++ ++ if (expected.name) ++ expected_name = xasprintf ("\"%s\"", expected.name); ++ else ++ expected_name = xstrdup ("NULL"); ++ ++ printf ("error: ttyname_r: actual {name=%s, ret=%d, errno=%d} != expected {name=%s, ret=%d, errno=%d}\n", ++ actual_name, actual.ret, actual.err, ++ expected_name, expected.ret, expected.err); ++ ++ free (actual_name); ++ free (expected_name); ++ return false; ++} ++ ++/* combined runner */ ++ ++static bool ++doit (int fd, const char *testname, struct result_r expected_r) ++{ ++ struct result expected = {.name=expected_r.name, .err=expected_r.ret}; ++ bool ret = true; ++ ++ printf ("info: testcase: %s\n", testname); ++ ++ if (!eq_ttyname (run_ttyname (fd), expected)) ++ ret = false; ++ if (!eq_ttyname_r (run_ttyname_r (fd), expected_r)) ++ ret = false; ++ ++ if (!ret) ++ support_record_failure (); ++ ++ return ret; ++} ++ ++/* chroot setup */ ++ ++static char *chrootdir; ++ ++static void ++prepare (int argc, char **argv) ++{ ++ chrootdir = xasprintf ("%s/tst-ttyname-XXXXXX", test_dir); ++ if (mkdtemp (chrootdir) == NULL) ++ FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", chrootdir); ++ add_temp_file (chrootdir); ++} ++#define PREPARE prepare ++ ++/* These chroot setup functions put the TTY at at "/console" (where it ++ won't be found by ttyname), and create "/dev/console" as an ++ ordinary file. This way, it's easier to write test-cases that ++ expect ttyname to fail; test-cases that expect it to succeed need ++ to explicitly remount it at "/dev/console". */ ++ ++static int ++do_in_chroot_1 (int (*cb)(const char *, int)) ++{ ++ printf ("info: entering chroot 1\n"); ++ ++ /* Open the PTS that we'll be testing on. */ ++ int master; ++ char *slavename; ++ VERIFY ((master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK)) >= 0); ++ VERIFY ((slavename = ptsname (master))); ++ VERIFY (unlockpt (master) == 0); ++ if (strncmp (slavename, "/dev/pts/", 9) != 0) ++ FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s", ++ slavename); ++ int slave = xopen (slavename, O_RDWR, 0); ++ if (!doit (slave, "basic smoketest", ++ (struct result_r){.name=slavename, .ret=0, .err=0})) ++ return 1; ++ ++ pid_t pid = xfork (); ++ if (pid == 0) ++ { ++ xclose (master); + -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ ++ if (!support_enter_mount_namespace ()) ++ FAIL_UNSUPPORTED ("could not enter new mount namespace"); + -+#include <bits/wordsize.h> ++ VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0); ++ VERIFY (chdir (chrootdir) == 0); + -+#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32 -+# define __LONG_DOUBLE_MATH_OPTIONAL 1 -+# ifndef __LONG_DOUBLE_128__ -+# define __NO_LONG_DOUBLE_MATH 1 -+# endif -+#endif -diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c -index c56f894a82..7d23df84d2 100644 ---- a/sysdeps/unix/sysv/linux/spawni.c -+++ b/sysdeps/unix/sysv/linux/spawni.c -@@ -17,7 +17,6 @@ - <http://www.gnu.org/licenses/>. */ - - #include <spawn.h> --#include <assert.h> - #include <fcntl.h> - #include <paths.h> - #include <string.h> -@@ -268,7 +267,6 @@ __spawni_child (void *arguments) - __sigprocmask (SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) - ? &attr->__ss : &args->oldmask, 0); - -- args->err = 0; - args->exec (args->file, args->argv, args->envp); - - /* This is compatibility function required to enable posix_spawn run -@@ -339,7 +337,7 @@ __spawnix (pid_t * pid, const char *file, - - /* Child must set args.err to something non-negative - we rely on - the parent and child sharing VM. */ -- args.err = -1; -+ args.err = 0; - args.file = file; - args.exec = exec; - args.fa = file_actions; -@@ -362,12 +360,26 @@ __spawnix (pid_t * pid, const char *file, - new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size, - CLONE_VM | CLONE_VFORK | SIGCHLD, &args); - -+ /* It needs to collect the case where the auxiliary process was created -+ but failed to execute the file (due either any preparation step or -+ for execve itself). */ - if (new_pid > 0) - { -+ /* Also, it handles the unlikely case where the auxiliary process was -+ terminated before calling execve as if it was successfully. The -+ args.err is set to 0 as default and changed to a positive value -+ only in case of failure, so in case of premature termination -+ due a signal args.err will remain zeroed and it will be up to -+ caller to actually collect it. */ - ec = args.err; -- assert (ec >= 0); -- if (ec != 0) -- __waitpid (new_pid, NULL, 0); -+ if (ec > 0) -+ /* There still an unlikely case where the child is cancelled after -+ setting args.err, due to a positive error value. Also there is -+ possible pid reuse race (where the kernel allocated the same pid -+ to an unrelated process). Unfortunately due synchronization -+ issues where the kernel might not have the process collected -+ the waitpid below can not use WNOHANG. */ -+ __waitpid (new_pid, NULL, 0); - } - else - ec = -new_pid; -diff --git a/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c -new file mode 100644 -index 0000000000..1240b846e6 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c -@@ -0,0 +1,27 @@ -+/* Check IOV_MAX definition: Helper function to capture UAPI header value. -+ Copyright (C) 2017 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. ++ xmkdir ("proc", 0755); ++ xmkdir ("dev", 0755); ++ xmkdir ("dev/pts", 0755); + -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. ++ VERIFY (mount ("/proc", "proc", NULL, MS_BIND|MS_REC, NULL) == 0); ++ VERIFY (mount ("devpts", "dev/pts", "devpts", ++ MS_NOSUID|MS_NOEXEC, ++ "newinstance,ptmxmode=0666,mode=620") == 0); ++ VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0); + -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. ++ touch ("console", 0); ++ touch ("dev/console", 0); ++ VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0); + -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ ++ xchroot ("."); + -+/* Use a separate function to avoid header compatibility issues. */ ++ char *linkname = xasprintf ("/proc/self/fd/%d", slave); ++ char *target = proc_fd_readlink (linkname); ++ VERIFY (strcmp (target, slavename) == 0); ++ free (linkname); + -+#include <linux/uio.h> ++ _exit (cb (slavename, slave)); ++ } ++ int status; ++ xwaitpid (pid, &status, 0); ++ VERIFY (WIFEXITED (status)); ++ xclose (master); ++ xclose (slave); ++ return WEXITSTATUS (status); ++} + -+long -+uio_maxiov_value (void) ++static int ++do_in_chroot_2 (int (*cb)(const char *, int)) +{ -+ return UIO_MAXIOV; ++ printf ("info: entering chroot 2\n"); ++ ++ int pid_pipe[2]; ++ xpipe (pid_pipe); ++ int exit_pipe[2]; ++ xpipe (exit_pipe); ++ ++ /* Open the PTS that we'll be testing on. */ ++ int master; ++ char *slavename; ++ VERIFY ((master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK)) >= 0); ++ VERIFY ((slavename = ptsname (master))); ++ VERIFY (unlockpt (master) == 0); ++ if (strncmp (slavename, "/dev/pts/", 9) != 0) ++ FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s", ++ slavename); ++ /* wait until in a new mount ns to open the slave */ ++ ++ /* enable `wait`ing on grandchildren */ ++ VERIFY (prctl (PR_SET_CHILD_SUBREAPER, 1) == 0); ++ ++ pid_t pid = xfork (); /* outer child */ ++ if (pid == 0) ++ { ++ xclose (master); ++ xclose (pid_pipe[0]); ++ xclose (exit_pipe[1]); ++ ++ if (!support_enter_mount_namespace ()) ++ FAIL_UNSUPPORTED ("could not enter new mount namespace"); ++ ++ int slave = xopen (slavename, O_RDWR, 0); ++ if (!doit (slave, "basic smoketest", ++ (struct result_r){.name=slavename, .ret=0, .err=0})) ++ _exit (1); ++ ++ VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0); ++ VERIFY (chdir (chrootdir) == 0); ++ ++ xmkdir ("proc", 0755); ++ xmkdir ("dev", 0755); ++ xmkdir ("dev/pts", 0755); ++ ++ VERIFY (mount ("devpts", "dev/pts", "devpts", ++ MS_NOSUID|MS_NOEXEC, ++ "newinstance,ptmxmode=0666,mode=620") == 0); ++ VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0); ++ ++ touch ("console", 0); ++ touch ("dev/console", 0); ++ VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0); ++ ++ xchroot ("."); ++ ++ if (unshare (CLONE_NEWNS | CLONE_NEWPID) < 0) ++ FAIL_UNSUPPORTED ("could not enter new PID namespace"); ++ pid = xfork (); /* inner child */ ++ if (pid == 0) ++ { ++ xclose (pid_pipe[1]); ++ ++ /* wait until the outer child has exited */ ++ char c; ++ VERIFY (read (exit_pipe[0], &c, 1) == 0); ++ xclose (exit_pipe[0]); ++ ++ VERIFY (mount ("proc", "/proc", "proc", ++ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) == 0); ++ ++ char *linkname = xasprintf ("/proc/self/fd/%d", slave); ++ char *target = proc_fd_readlink (linkname); ++ VERIFY (strcmp (target, strrchr (slavename, '/')) == 0); ++ free (linkname); ++ ++ _exit (cb (slavename, slave)); ++ } ++ xwrite (pid_pipe[1], &pid, sizeof pid); ++ _exit (0); ++ } ++ xclose (pid_pipe[1]); ++ xclose (exit_pipe[0]); ++ xclose (exit_pipe[1]); ++ ++ /* wait for the outer child */ ++ int status; ++ xwaitpid (pid, &status, 0); ++ VERIFY (WIFEXITED (status)); ++ int ret = WEXITSTATUS (status); ++ if (ret != 0) ++ return ret; ++ ++ /* set 'pid' to the inner child */ ++ VERIFY (read (pid_pipe[0], &pid, sizeof pid) == sizeof pid); ++ xclose (pid_pipe[0]); ++ ++ /* wait for the inner child */ ++ xwaitpid (pid, &status, 0); ++ VERIFY (WIFEXITED (status)); ++ xclose (master); ++ return WEXITSTATUS (status); +} -diff --git a/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c -new file mode 100644 -index 0000000000..dfdf3da484 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c -@@ -0,0 +1,40 @@ -+/* Check IOV_MAX definition for consistency (bug 22321). -+ Copyright (C) 2017 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. + -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. ++/* main test */ + -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. ++static int ++run_chroot_tests (const char *slavename, int slave) ++{ ++ struct stat st; ++ bool ok = true; + -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ ++ /* There are 3 groups of tests here. The first group fairly ++ generically does things known to mess up ttyname, and verifies ++ that ttyname copes correctly. The remaining groups are ++ increasingly convoluted, as we target specific parts of ttyname ++ to try to confuse. */ + -+/* Defined in tst-sysconf-iov_max-uapi.c. */ -+long uio_maxiov_value (void); ++ /* Basic tests that it doesn't get confused by multiple devpts ++ instances. */ ++ { ++ VERIFY (stat (slavename, &st) < 0); /* sanity check */ ++ if (!doit (slave, "no conflict, no match", ++ (struct result_r){.name=NULL, .ret=ENODEV, .err=ENODEV})) ++ ok = false; ++ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0); ++ if (!doit (slave, "no conflict, console", ++ (struct result_r){.name="/dev/console", .ret=0, .err=0})) ++ ok = false; ++ VERIFY (umount ("/dev/console") == 0); ++ ++ /* keep creating PTYs until we we get a name collision */ ++ while (stat (slavename, &st) < 0) ++ posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK); ++ VERIFY (stat (slavename, &st) == 0); ++ ++ if (!doit (slave, "conflict, no match", ++ (struct result_r){.name=NULL, .ret=ENODEV, .err=ENODEV})) ++ ok = false; ++ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0); ++ if (!doit (slave, "conflict, console", ++ (struct result_r){.name="/dev/console", .ret=0, .err=0})) ++ ok = false; ++ VERIFY (umount ("/dev/console") == 0); ++ } + ++ /* The first tests kinda assumed that they hit certain code-paths ++ based on assuming that the readlink target is 'slavename', but ++ that's not quite always true. They're still a good preliminary ++ sanity check, so keep them, but let's add tests that make sure ++ that those code-paths are hit by doing a readlink ourself. */ ++ { ++ char *linkname = xasprintf ("/proc/self/fd/%d", slave); ++ char *target = proc_fd_readlink (linkname); ++ free (linkname); ++ /* Depeding on how we set up the chroot, the kernel may or may not ++ trim the leading path to the target (it may give us "/6", ++ instead of "/dev/pts/6"). We test it both ways (do_in_chroot_1 ++ and do_in_chroot_2). This test group relies on the target ++ existing, so guarantee that it does exist by creating it if ++ necessary. */ ++ if (stat (target, &st) < 0) ++ { ++ VERIFY (errno == ENOENT); ++ touch (target, 0); ++ } + -+#include <limits.h> -+#include <support/check.h> -+#include <sys/uio.h> -+#include <unistd.h> ++ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0); ++ VERIFY (mount ("/console", target, NULL, MS_BIND, NULL) == 0); ++ if (!doit (slave, "with readlink target", ++ (struct result_r){.name=target, .ret=0, .err=0})) ++ ok = false; ++ VERIFY (umount (target) == 0); ++ VERIFY (umount ("/dev/console") == 0); ++ ++ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0); ++ VERIFY (mount (slavename, target, NULL, MS_BIND, NULL) == 0); ++ if (!doit (slave, "with readlink trap; fallback", ++ (struct result_r){.name="/dev/console", .ret=0, .err=0})) ++ ok = false; ++ VERIFY (umount (target) == 0); ++ VERIFY (umount ("/dev/console") == 0); ++ ++ VERIFY (mount (slavename, target, NULL, MS_BIND, NULL) == 0); ++ if (!doit (slave, "with readlink trap; no fallback", ++ (struct result_r){.name=NULL, .ret=ENODEV, .err=ENODEV})) ++ ok = false; ++ VERIFY (umount (target) == 0); ++ } ++ ++ /* This test makes sure that everything still works OK if readdir ++ finds a pseudo-match before and/or after the actual match. Now, ++ to do that, we need to control that readdir finds the ++ pseudo-matches before and after the actual match; and there's no ++ good way to control that order in absence of whitebox testing. ++ So, just create 3 files, then use opendir/readdir to see what ++ order they are in, and assign meaning based on that order, not by ++ name; assigning the first to be a pseudo-match, the second to be ++ the actual match, and the third to be a pseudo-match. This ++ assumes that (on tmpfs) ordering within the directory is stable ++ in the absence of modification, which seems reasonably safe. */ ++ { ++ /* since we're testing the fallback search, disable the readlink ++ happy-path */ ++ VERIFY (umount2 ("/proc", MNT_DETACH) == 0); ++ ++ touch ("/dev/console1", 0); ++ touch ("/dev/console2", 0); ++ touch ("/dev/console3", 0); ++ ++ char *c[3]; ++ int ci = 0; ++ DIR *dirstream = opendir ("/dev"); ++ VERIFY (dirstream != NULL); ++ struct dirent *d; ++ while ((d = readdir (dirstream)) != NULL && ci < 3) ++ { ++ if (strcmp (d->d_name, "console1") && ++ strcmp (d->d_name, "console2") && ++ strcmp (d->d_name, "console3") ) ++ continue; ++ c[ci++] = xasprintf ("/dev/%s", d->d_name); ++ } ++ VERIFY (ci == 3); ++ VERIFY (closedir (dirstream) == 0); ++ ++ VERIFY (mount (slavename, c[0], NULL, MS_BIND, NULL) == 0); ++ VERIFY (mount ("/console", c[1], NULL, MS_BIND, NULL) == 0); ++ VERIFY (mount (slavename, c[2], NULL, MS_BIND, NULL) == 0); ++ VERIFY (umount2 ("/dev/pts", MNT_DETACH) == 0); ++ if (!doit (slave, "with search-path trap", ++ (struct result_r){.name=c[1], .ret=0, .err=0})) ++ ok = false; ++ for (int i = 0; i < 3; i++) ++ { ++ VERIFY (umount (c[i]) == 0); ++ VERIFY (unlink (c[i]) == 0); ++ free (c[i]); ++ } ++ } ++ ++ return ok ? 0 : 1; ++} + +static int +do_test (void) +{ -+ TEST_VERIFY (_XOPEN_IOV_MAX == 16); /* Value required by POSIX. */ -+ TEST_VERIFY (uio_maxiov_value () >= _XOPEN_IOV_MAX); -+ TEST_VERIFY (IOV_MAX == uio_maxiov_value ()); -+ TEST_VERIFY (UIO_MAXIOV == uio_maxiov_value ()); -+ TEST_VERIFY (sysconf (_SC_UIO_MAXIOV) == uio_maxiov_value ()); -+ TEST_VERIFY (sysconf (_SC_IOV_MAX) == uio_maxiov_value ()); -+ return 0; ++ support_become_root (); ++ ++ int ret1 = do_in_chroot_1 (run_chroot_tests); ++ if (ret1 == EXIT_UNSUPPORTED) ++ return ret1; ++ ++ int ret2 = do_in_chroot_2 (run_chroot_tests); ++ if (ret2 == EXIT_UNSUPPORTED) ++ return ret2; ++ ++ return ret1 | ret2; +} + +#include <support/test-driver.c> +diff --git a/sysdeps/unix/sysv/linux/ttyname.c b/sysdeps/unix/sysv/linux/ttyname.c +index 5909cb765f..f4c955f25b 100644 +--- a/sysdeps/unix/sysv/linux/ttyname.c ++++ b/sysdeps/unix/sysv/linux/ttyname.c +@@ -35,16 +35,14 @@ + char *__ttyname; + #endif + +-static char *getttyname (const char *dev, dev_t mydev, +- ino64_t myino, int save, int *dostat) +- internal_function; +- ++static char *getttyname (const char *dev, const struct stat64 *mytty, ++ int save, int *dostat); + + libc_freeres_ptr (static char *getttyname_name); + + static char * +-internal_function attribute_compat_text_section +-getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat) ++attribute_compat_text_section ++getttyname (const char *dev, const struct stat64 *mytty, int save, int *dostat) + { + static size_t namelen; + struct stat64 st; +@@ -65,7 +63,7 @@ getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat) + *((char *) __mempcpy (getttyname_name, dev, devlen - 1)) = '/'; + + while ((d = __readdir64 (dirstream)) != NULL) +- if ((d->d_fileno == myino || *dostat) ++ if ((d->d_fileno == mytty->st_ino || *dostat) + && strcmp (d->d_name, "stdin") + && strcmp (d->d_name, "stdout") + && strcmp (d->d_name, "stderr")) +@@ -87,12 +85,7 @@ getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat) + } + memcpy (&getttyname_name[devlen], d->d_name, dlen); + if (__xstat64 (_STAT_VER, getttyname_name, &st) == 0 +-#ifdef _STATBUF_ST_RDEV +- && S_ISCHR (st.st_mode) && st.st_rdev == mydev +-#else +- && d->d_fileno == myino && st.st_dev == mydev +-#endif +- ) ++ && is_mytty (mytty, &st)) + { + (void) __closedir (dirstream); + #if 0 +@@ -122,6 +115,7 @@ ttyname (int fd) + char procname[30]; + struct stat64 st, st1; + int dostat = 0; ++ int doispty = 0; + char *name; + int save = errno; + struct termios term; +@@ -169,30 +163,15 @@ ttyname (int fd) + /* Verify readlink result, fall back on iterating through devices. */ + if (ttyname_buf[0] == '/' + && __xstat64 (_STAT_VER, ttyname_buf, &st1) == 0 +-#ifdef _STATBUF_ST_RDEV +- && S_ISCHR (st1.st_mode) +- && st1.st_rdev == st.st_rdev +-#endif +- && st1.st_ino == st.st_ino +- && st1.st_dev == st.st_dev) ++ && is_mytty (&st, &st1)) + return ttyname_buf; + +- /* If the link doesn't exist, then it points to a device in another +- namespace. */ +- if (is_pty (&st)) +- { +- __set_errno (ENODEV); +- return NULL; +- } ++ doispty = 1; + } + + if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode)) + { +-#ifdef _STATBUF_ST_RDEV +- name = getttyname ("/dev/pts", st.st_rdev, st.st_ino, save, &dostat); +-#else +- name = getttyname ("/dev/pts", st.st_dev, st.st_ino, save, &dostat); +-#endif ++ name = getttyname ("/dev/pts", &st, save, &dostat); + } + else + { +@@ -202,21 +181,23 @@ ttyname (int fd) + + if (!name && dostat != -1) + { +-#ifdef _STATBUF_ST_RDEV +- name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat); +-#else +- name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat); +-#endif ++ name = getttyname ("/dev", &st, save, &dostat); + } + + if (!name && dostat != -1) + { + dostat = 1; +-#ifdef _STATBUF_ST_RDEV +- name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat); +-#else +- name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat); +-#endif ++ name = getttyname ("/dev", &st, save, &dostat); ++ } ++ ++ if (!name && doispty && is_pty (&st)) ++ { ++ /* We failed to figure out the TTY's name, but we can at least ++ signal that we did verify that it really is a PTY slave. ++ This happens when we have inherited the file descriptor from ++ a different mount namespace. */ ++ __set_errno (ENODEV); ++ return NULL; + } + + return name; +diff --git a/sysdeps/unix/sysv/linux/ttyname.h b/sysdeps/unix/sysv/linux/ttyname.h +index 2e415e4e9c..48181330a9 100644 +--- a/sysdeps/unix/sysv/linux/ttyname.h ++++ b/sysdeps/unix/sysv/linux/ttyname.h +@@ -16,13 +16,15 @@ + not, see <http://www.gnu.org/licenses/>. */ + + #include <unistd.h> ++#include <stdbool.h> + #include <sys/sysmacros.h> + #include <sys/types.h> + #include <sys/stat.h> + + /* Return true if this is a UNIX98 pty device, as defined in +- linux/Documentation/devices.txt. */ +-static inline int ++ linux/Documentation/devices.txt (on linux < 4.10) or ++ linux/Documentation/admin-guide/devices.txt (on linux >= 4.10). */ ++static inline bool + is_pty (struct stat64 *sb) + { + #ifdef _STATBUF_ST_RDEV +@@ -32,3 +34,15 @@ is_pty (struct stat64 *sb) + return false; + #endif + } ++ ++static inline bool ++is_mytty (const struct stat64 *mytty, const struct stat64 *maybe) ++{ ++ return (maybe->st_ino == mytty->st_ino ++ && maybe->st_dev == mytty->st_dev ++#ifdef _STATBUF_ST_RDEV ++ && S_ISCHR (maybe->st_mode) ++ && maybe->st_rdev == mytty->st_rdev ++#endif ++ ); ++} +diff --git a/sysdeps/unix/sysv/linux/ttyname_r.c b/sysdeps/unix/sysv/linux/ttyname_r.c +index dc863526ba..00eefc2c5c 100644 +--- a/sysdeps/unix/sysv/linux/ttyname_r.c ++++ b/sysdeps/unix/sysv/linux/ttyname_r.c +@@ -31,12 +31,12 @@ + #include "ttyname.h" + + static int getttyname_r (char *buf, size_t buflen, +- dev_t mydev, ino64_t myino, int save, +- int *dostat) internal_function; ++ const struct stat64 *mytty, int save, ++ int *dostat); + + static int +-internal_function attribute_compat_text_section +-getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino, ++attribute_compat_text_section ++getttyname_r (char *buf, size_t buflen, const struct stat64 *mytty, + int save, int *dostat) + { + struct stat64 st; +@@ -52,7 +52,7 @@ getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino, + } + + while ((d = __readdir64 (dirstream)) != NULL) +- if ((d->d_fileno == myino || *dostat) ++ if ((d->d_fileno == mytty->st_ino || *dostat) + && strcmp (d->d_name, "stdin") + && strcmp (d->d_name, "stdout") + && strcmp (d->d_name, "stderr")) +@@ -72,12 +72,7 @@ getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino, + cp[0] = '\0'; + + if (__xstat64 (_STAT_VER, buf, &st) == 0 +-#ifdef _STATBUF_ST_RDEV +- && S_ISCHR (st.st_mode) && st.st_rdev == mydev +-#else +- && d->d_fileno == myino && st.st_dev == mydev +-#endif +- ) ++ && is_mytty (mytty, &st)) + { + (void) __closedir (dirstream); + __set_errno (save); +@@ -100,6 +95,7 @@ __ttyname_r (int fd, char *buf, size_t buflen) + char procname[30]; + struct stat64 st, st1; + int dostat = 0; ++ int doispty = 0; + int save = errno; + + /* Test for the absolute minimal size. This makes life easier inside +@@ -151,22 +147,10 @@ __ttyname_r (int fd, char *buf, size_t buflen) + /* Verify readlink result, fall back on iterating through devices. */ + if (buf[0] == '/' + && __xstat64 (_STAT_VER, buf, &st1) == 0 +-#ifdef _STATBUF_ST_RDEV +- && S_ISCHR (st1.st_mode) +- && st1.st_rdev == st.st_rdev +-#endif +- && st1.st_ino == st.st_ino +- && st1.st_dev == st.st_dev) ++ && is_mytty (&st, &st1)) + return 0; + +- /* If the link doesn't exist, then it points to a device in another +- * namespace. +- */ +- if (is_pty (&st)) +- { +- __set_errno (ENODEV); +- return ENODEV; +- } ++ doispty = 1; + } + + /* Prepare the result buffer. */ +@@ -175,13 +159,8 @@ __ttyname_r (int fd, char *buf, size_t buflen) + + if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode)) + { +-#ifdef _STATBUF_ST_RDEV +- ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, ++ ret = getttyname_r (buf, buflen, &st, save, + &dostat); +-#else +- ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, +- &dostat); +-#endif + } + else + { +@@ -193,26 +172,26 @@ __ttyname_r (int fd, char *buf, size_t buflen) + { + buf[sizeof ("/dev/") - 1] = '\0'; + buflen += sizeof ("pts/") - 1; +-#ifdef _STATBUF_ST_RDEV +- ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, +- &dostat); +-#else +- ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, ++ ret = getttyname_r (buf, buflen, &st, save, + &dostat); +-#endif + } + + if (ret && dostat != -1) + { + buf[sizeof ("/dev/") - 1] = '\0'; + dostat = 1; +-#ifdef _STATBUF_ST_RDEV +- ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, ++ ret = getttyname_r (buf, buflen, &st, + save, &dostat); +-#else +- ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, +- save, &dostat); +-#endif ++ } ++ ++ if (ret && doispty && is_pty (&st)) ++ { ++ /* We failed to figure out the TTY's name, but we can at least ++ signal that we did verify that it really is a PTY slave. ++ This happens when we have inherited the file descriptor from ++ a different mount namespace. */ ++ __set_errno (ENODEV); ++ return ENODEV; + } + + return ret; diff --git a/sysdeps/unix/sysv/linux/wordsize-64/glob64.c b/sysdeps/unix/sysv/linux/wordsize-64/glob64.c deleted file mode 100644 index eab7703d5c..0000000000 -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-glibc/glibc.git