summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog135
-rw-r--r--NEWS4
-rw-r--r--elf/dl-minimal.c3
-rw-r--r--fedora/branch.mk4
-rw-r--r--fedora/glibc.spec.in15
-rw-r--r--iconvdata/Makefile9
-rw-r--r--iconvdata/TESTS3
-rw-r--r--iconvdata/brf.c29
-rw-r--r--iconvdata/gconv-modules6
-rw-r--r--iconvdata/testdata/BRF7
-rw-r--r--iconvdata/testdata/BRF..UTF87
-rwxr-xr-xiconvdata/tst-tables.sh3
-rw-r--r--localedata/ChangeLog5
-rw-r--r--localedata/charmaps/BRF108
-rw-r--r--misc/hsearch_r.c7
-rw-r--r--nptl/ChangeLog7
-rw-r--r--nptl/pthread_join.c4
-rw-r--r--nptl/tst-initializers1.c5
-rw-r--r--nscd/connections.c1
-rw-r--r--nscd/nscd-client.h11
-rw-r--r--nscd/nscd_getai.c71
-rw-r--r--nscd/nscd_getgr_r.c108
-rw-r--r--nscd/nscd_gethst_r.c143
-rw-r--r--nscd/nscd_getpw_r.c70
-rw-r--r--nscd/nscd_getserv_r.c126
-rw-r--r--nscd/nscd_helper.c153
-rw-r--r--nscd/nscd_initgroups.c62
-rw-r--r--scripts/gen-as-const.awk2
-rw-r--r--stdio-common/Makefile4
-rw-r--r--stdio-common/_itoa.c57
-rw-r--r--stdio-common/_itoa.h13
-rw-r--r--stdio-common/_itowa.c41
-rw-r--r--stdio-common/bug17.c31
-rw-r--r--string/Makefile2
-rw-r--r--string/Versions3
-rw-r--r--string/strerror_l.c71
-rw-r--r--string/string.h8
-rw-r--r--sysdeps/i386/bits/byteswap.h6
-rw-r--r--sysdeps/i386/dl-trampoline.S18
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_ceill.c7
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_copysignl.c15
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_fabsl.c4
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_floorl.c8
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_roundl.c7
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_truncl.c7
-rw-r--r--sysdeps/unix/sysv/linux/getdents.c5
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.h18
-rw-r--r--sysdeps/unix/sysv/linux/sys/personality.h11
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/sysdep.h31
-rw-r--r--sysdeps/x86_64/bits/byteswap.h6
-rw-r--r--wcsmbs/wchar.h6
51 files changed, 1046 insertions, 441 deletions
diff --git a/ChangeLog b/ChangeLog
index 17172269a3..55f92a09af 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,138 @@
+2007-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/sysdep.h (PTR_MANGLE): Roll value before
+	returning.
+	(PTR_DEMANGLE): Real definition now that it's not the same as
+	PRT_MANGLE anymore.
+	* sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise.
+
+	* string/strerror_l.c: New file.
+	* string/Makefile (routines): Add strerror_l.
+	* string/string.h: Declare strerror_l.
+	* string/Versions: Export strerror_l for GLIBC_2.6.
+
+2007-01-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* nscd/nscd_helper.c (open_socket): Now takes request type and key
+	as parameter.  Construct request record.  Try sending request
+	before the first poll use, it usually succeeds.  Adjust all
+	callers.
+	* nscd/nscd-client.h: Define MAXKEYLEN.
+	* nscd/connections.c (nscd_run): Don't define MAXKEYLEN here.
+
+2007-01-31  Jakub Jelinek  <jakub@redhat.com>
+
+	* nscd/nscd-client.h (__nscd_cache_search): Remove const qualifier
+	from return value.
+	* nscd/nscd_helper.c: Include string.h.
+	(__nscd_cache_search): Remove const qualifier from return value.
+	On strict alignment architectures check hash entry and data head
+	alignment.
+	* nscd/nscd_getpw_r.c (nscd_getpw_r): Don't crash or fail because
+	mmapped data during GC cycle contains garbage.  If
+	__nscd_drop_map_ref fails, decrement mapped->counter when returning
+	error or if retrying with NO_MAPPING, only __nscd_unmap if counter
+	dropped to 0.
+	* nscd/nscd_getgr_r.c (nscd_getgr_r): Likewise.
+	* nscd/nscd_initgroups.c (__nscd_getgrouplist): Likewise.
+	* nscd/nscd_gethst_r.c (nscd_gethst_r): Likewise.
+	* nscd/nscd_getai.c (__nscd_getai): Likewise.
+	* nscd/nscd_getserv_r.c (nscd_getserv_r): Likewise.
+
+2007-01-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* misc/hsearch_r.c (hdestroy_r): Remove unnecessary test.
+
+2007-01-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/dl-trampoline.S (_dl_runtime_profile): Use register
+	names not numbers in cfi_*.
+
+2007-01-26  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/unix/sysv/linux/sys/personality.h (ADDR_NO_RANDOMIZE,
+	ADDR_LIMIT_3GB, PER_LINUX_32BIT, PER_LINUX32_3GB): Add.
+	Correct values of PER_HPUX and PER_OSF4.
+
+2007-01-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf/dl-minimal.c: Undefine _itoa first.
+	* stdio-common/_itoa.h: Define _itoa and _fitoa for 64-bit platforms.
+	* malloc/mtrace.c: Revert last change.
+	* posix/wordexp.c: Likewise.
+
+2007-01-24  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/i386/bits/byteswap.h (__bswap_32): Add __nocona__, __core2__
+	and __geode__ to the list of i486+ CPUs.
+	* sysdeps/x86_64/bits/byteswap.h (__bswap_32): Likewise.
+
+2007-01-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* stdio-common/_itoa.c: Include <limits.h>.
+	* stdio-common/_itowa.c: Likewise.
+
+2007-01-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* stdio-common/_itowa.c: Don't compile _itowa for 64-bit
+	platforms.
+	* stdio-common/_itoa.c: Don't compile in _itoa and _fitoa for
+	64-bit platforms.
+	* malloc/mtrace.c (tr_where): Use _fitoa_word instead of _fitoa if
+	possible.
+	* posix/wordexp.c (parse_arith): Use _itoa_word instead of _itoa
+	if possible.
+
+	[BZ #3902]
+	* stdio-common/_itoa.c (_itoa): Make sure at least a zero is emitted.
+	* stdio-common/Makefile (tests): Add bug17.
+	* stdio-common/bug17.c: New file.
+
+2007-01-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* iconvdata/brf.c: New file.
+	* iconvdata/testdata/BRF: New file.
+	* iconvdata/testdata/BRF..UTF8: New file.
+	Contributed by Samuel Thibault <samuel.thibault@ens-lyon.org>.
+	* iconvdata/Makefile: Add rules to build BRF.
+	* iconvdata/TESTS: Add BRF entry.
+	* iconvdata/gconv-modules: Likewise.
+	* iconvdata/tst-tables.sh: Likewise.
+
+2007-01-18  Anton Nikishaev  <anton.nik@gmail.com>
+
+	* wcsmbs/wchar.h (wcstoll): Fix comment, function returns value of
+	type `long long int', not `long int'.
+	(wcstoq): Likewise.
+
+2007-01-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* scripts/gen-as-const.awk: Add cast to long to avoid int promotion
+	of values on 64-bit platforms which are too large.
+
+2007-01-12  Steven Munroe  <sjmunroe@us.ibm.com>
+	    Joe Kerian  <jkerian@us.us.ibm.com>
+
+	[BZ #2749]
+	* sysdeps/ieee754/ldbl-128ibm/s_copysignl.c: Include
+	<math_ldbl_opt.h>.  Remove weak_alias.  Use long_double_symbol macro.
+	(__copysignl): Use signbit() for comparison.
+	* sysdeps/ieee754/ldbl-128ibm/s_fabsl.c (__fabsl): Correct parms for
+	SET_LDOUBLE_WORDS64.
+
+	[BZ #2423, #2749]
+	* sysdeps/ieee754/ldbl-128ibm/s_ceill.c: Don't include <fenv_libc.h>.
+	(__ceill): Remove calls to fegetround(), fesetround().
+	* sysdeps/ieee754/ldbl-128ibm/s_floorl.c: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_roundl.c: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_truncl.c: Likewise.
+
+2007-01-17  Jakub Jelinek  <jakub@redhat.com>
+
+	* nscd/nscd_getserv_r.c (nscd_getserv_r): Fix pastos.
+
+	* sysdeps/unix/sysv/linux/getdents.c (offsetof): Remove.
+
 2007-01-17  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/unix/sysv/linux/fatal-prepare.h: Use PTHFCT_CALL to
diff --git a/NEWS b/NEWS
index a32179fe6a..69414e0203 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  2007-1-13
+GNU C Library NEWS -- history of user-visible changes.  2007-2-1
 Copyright (C) 1992-2006, 2007 Free Software Foundation, Inc.
 See the end for copying conditions.
 
@@ -9,6 +9,8 @@ Version 2.6
 
 * New Linux interfaces: epoll_pwait.
 
+* New generic interfaces: strerror_l.
+
 * nscd can now cache the services database.   Implemented by Ulrich Drepper.
 
 
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c
index 8e78709b5a..45524088e9 100644
--- a/elf/dl-minimal.c
+++ b/elf/dl-minimal.c
@@ -1,5 +1,5 @@
 /* Minimal replacements for basic facilities used in the dynamic linker.
-   Copyright (C) 1995-1998,2000-2002,2004,2005,2006
+   Copyright (C) 1995-1998,2000-2002,2004-2006,2007
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -283,6 +283,7 @@ __strtoul_internal (const char *nptr, char **endptr, int base, int group)
 }
 
 
+#undef _itoa
 /* We always use _itoa instead of _itoa_word in ld.so since the former
    also has to be present and it is never about speed when these
    functions are used.  */
diff --git a/fedora/branch.mk b/fedora/branch.mk
index e4217bc04b..37e8ff5e8f 100644
--- a/fedora/branch.mk
+++ b/fedora/branch.mk
@@ -3,5 +3,5 @@ glibc-branch := fedora
 glibc-base := HEAD
 DIST_BRANCH := devel
 COLLECTION := dist-fc7
-fedora-sync-date := 2007-01-17 10:43 UTC
-fedora-sync-tag := fedora-glibc-20070117T1043
+fedora-sync-date := 2007-02-02 09:23 UTC
+fedora-sync-tag := fedora-glibc-20070202T0923
diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in
index 8b2027346c..14015daa1d 100644
--- a/fedora/glibc.spec.in
+++ b/fedora/glibc.spec.in
@@ -1,4 +1,4 @@
-%define glibcrelease 15
+%define glibcrelease 16
 %define auxarches i586 i686 athlon sparcv9 alphaev6
 %define xenarches i686 athlon
 %ifarch %{xenarches}
@@ -1393,7 +1393,7 @@ touch $RPM_BUILD_ROOT/%{_prefix}/lib/locale/locale-archive
 %triggerin common -p /usr/sbin/tzdata-update -- tzdata
 
 %post devel
-/sbin/install-info %{_infodir}/libc.info.gz %{_infodir}/dir
+/sbin/install-info %{_infodir}/libc.info.gz %{_infodir}/dir || :
 
 %pre headers
 # this used to be a link and it is causing nightmares now
@@ -1403,7 +1403,7 @@ fi
 
 %preun devel
 if [ "$1" = 0 ]; then
-    /sbin/install-info --delete %{_infodir}/libc.info.gz %{_infodir}/dir
+    /sbin/install-info --delete %{_infodir}/libc.info.gz %{_infodir}/dir || :
 fi
 
 %post utils -p /sbin/ldconfig
@@ -1546,6 +1546,15 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Fri Feb  2 2007 Jakub Jelinek <jakub@redhat.com> 2.5.90-16
+- add strerror_l
+- fix application crashes when doing NSS lookups through nscd
+  mmapped databases and nscd decides to start garbage collection
+  during the lookups (#219145, #225315)
+- fix %0lld printing of 0LL on 32-bit architectures (BZ#3902)
+- ignore errors from install-info in glibc-devel scriptlets
+  (#223691)
+
 * Wed Jan 17 2007 Jakub Jelinek <jakub@redhat.com> 2.5.90-15
 - fix NIS getservbyname when proto is NULL
 - fix nss_compat +group handling (#220658)
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
index c7d5801c6c..8b49367bd4 100644
--- a/iconvdata/Makefile
+++ b/iconvdata/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1997-2004,2005,2006 Free Software Foundation, Inc.
+# Copyright (C) 1997-2004,2005,2006,2007 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
@@ -58,7 +58,7 @@ modules	:= ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5		 \
 	   IBM1142 IBM1143 IBM1144 IBM1145 IBM1146 IBM1147 IBM1148 	 \
 	   IBM1149 IBM1166 IBM1167 IBM4517 IBM4899 IBM4909 IBM4971 	 \
 	   IBM5347 IBM9030 IBM9066 IBM9448 IBM12712 IBM16804             \
-	   IBM1364 IBM1371 IBM1388 IBM1390 IBM1399 ISO_11548-1 MIK
+	   IBM1364 IBM1371 IBM1388 IBM1390 IBM1399 ISO_11548-1 MIK BRF
 
 modules.so := $(addsuffix .so, $(modules))
 
@@ -196,7 +196,8 @@ distribute := gconv-modules extra-module.mk gap.awk gaptab.awk gconv.map    \
 	      ibm9030.c ibm9030.h ibm9066.c ibm9066.h ibm9448.c ibm9448.h   \
 	      ibm12712.c ibm12712.h ibm16804.c ibm16804.h                   \
 	      ibm1364.c ibm1364.h ibm1371.c ibm1371.h ibm1388.c ibm1388.h   \
-	      ibm1390.c ibm1390.h ibm1399.c ibm1399.h iso_11548-1.c mik.c
+	      ibm1390.c ibm1390.h ibm1399.c ibm1399.h iso_11548-1.c mik.c   \
+	      brf.c
 
 # We build the transformation modules only when we build shared libs.
 ifeq (yes,$(build-shared))
@@ -237,7 +238,7 @@ gen-8bit-gap-modules := koi8-r latin-greek latin-greek-1 ibm256 ibm273	   \
 			iso8859-13 iso8859-14 iso8859-15 mac-uk sami-ws2   \
 			iso-ir-197 tis-620 koi8-u ibm874 cp10007 koi8-t	   \
 			georgian-ps georgian-academy iso-ir-209 mac-sami   \
-			iso8859-11 ibm866nav pt154 rk1048 mik
+			iso8859-11 ibm866nav pt154 rk1048 mik brf
 
 gen-special-modules := iso8859-7jp
 
diff --git a/iconvdata/TESTS b/iconvdata/TESTS
index b70e5051f0..2743cc1ff6 100644
--- a/iconvdata/TESTS
+++ b/iconvdata/TESTS
@@ -1,5 +1,5 @@
 # Available tests for iconv(1) (and therefore iconv(3)) in GNU libc.
-# Copyright (C) 1998-2002, 2005 Free Software Foundation, Inc.
+# Copyright (C) 1998-2002, 2005, 2007 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 # Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 #
@@ -166,3 +166,4 @@ IBM1390			IBM1390			N	UTF8
 IBM1399			IBM1399			N	UTF8
 ISO_11548-1		ISO_11548-1		-	UTF8
 MIK			MIK			Y	UTF8
+BRF			BRF			-	UTF8
diff --git a/iconvdata/brf.c b/iconvdata/brf.c
new file mode 100644
index 0000000000..4e40e7b02a
--- /dev/null
+++ b/iconvdata/brf.c
@@ -0,0 +1,29 @@
+/* Conversion from and to BRF.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Samuel Thibault <samuel.thibault@ens-lyon.org>, 2006.
+
+   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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <stdint.h>
+
+/* Get the conversion table.  */
+#define TABLES <brf.h>
+
+#define CHARSET_NAME	"BRF//"
+#define HAS_HOLES	1	/* Not all 256 character are defined.  */
+
+#include <8bit-gap.c>
diff --git a/iconvdata/gconv-modules b/iconvdata/gconv-modules
index 852c7b94a6..7f47dec5ed 100644
--- a/iconvdata/gconv-modules
+++ b/iconvdata/gconv-modules
@@ -1,5 +1,5 @@
 # GNU libc iconv configuration.
-# Copyright (C) 1997-2004, 2005 Free Software Foundation, Inc.
+# Copyright (C) 1997-2004, 2005, 2007 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
@@ -1907,3 +1907,7 @@ module	INTERNAL		ISO_11548-1//		ISO_11548-1	1
 #	from			to			module		cost
 module	MIK//			INTERNAL		MIK		1
 module	INTERNAL		MIK//			MIK		1
+
+#	from			to			module		cost
+module	BRF//			INTERNAL		BRF		1
+module	INTERNAL		BRF//			BRF		1
diff --git a/iconvdata/testdata/BRF b/iconvdata/testdata/BRF
new file mode 100644
index 0000000000..a69e107243
--- /dev/null
+++ b/iconvdata/testdata/BRF
@@ -0,0 +1,7 @@
+A B C D E F G H I J
+K L M N O P Q R S T
+U V X Y Z & = ( ! )
+* < % ? : $ ] \ [ W
+1 2 3 4 5 6 7 8 9 0
+/ + # > ' -
+@ ^ _ " . ; ,
diff --git a/iconvdata/testdata/BRF..UTF8 b/iconvdata/testdata/BRF..UTF8
new file mode 100644
index 0000000000..08275e232f
--- /dev/null
+++ b/iconvdata/testdata/BRF..UTF8
@@ -0,0 +1,7 @@
+⠁⠀⠃⠀⠉⠀⠙⠀⠑⠀⠋⠀⠛⠀⠓⠀⠊⠀⠚
+⠅⠀⠇⠀⠍⠀⠝⠀⠕⠀⠏⠀⠟⠀⠗⠀⠎⠀⠞
+⠥⠀⠧⠀⠭⠀⠽⠀⠵⠀⠯⠀⠿⠀⠷⠀⠮⠀⠾
+⠡⠀⠣⠀⠩⠀⠹⠀⠱⠀⠫⠀⠻⠀⠳⠀⠪⠀⠺
+⠂⠀⠆⠀⠒⠀⠲⠀⠢⠀⠖⠀⠶⠀⠦⠀⠔⠀⠴
+⠌⠀⠬⠀⠼⠀⠜⠀⠄⠀⠤
+⠈⠀⠘⠀⠸⠀⠐⠀⠨⠀⠰⠀⠠
diff --git a/iconvdata/tst-tables.sh b/iconvdata/tst-tables.sh
index 506adbcd7c..be1e8832a5 100755
--- a/iconvdata/tst-tables.sh
+++ b/iconvdata/tst-tables.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 2000,2001,2002,2003,2004,2007 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 # Contributed by Bruno Haible <haible@clisp.cons.org>, 2000.
 #
@@ -208,6 +208,7 @@ cat <<EOF |
   PT154
   RK1048
   MIK
+  BRF
   #
   # Multibyte encodings come here
   #
diff --git a/localedata/ChangeLog b/localedata/ChangeLog
index 85b2d7948d..39e87c2dd4 100644
--- a/localedata/ChangeLog
+++ b/localedata/ChangeLog
@@ -1,3 +1,8 @@
+2007-01-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* charmaps/BRF: New file.
+	Contributed by Samuel Thibault <samuel.thibault@ens-lyon.org>.
+
 2006-12-05  Jakub Jelinek  <jakub@redhat.com>
 
 	* locales/cs_CZ (LC_TIME): Change d_fmt to %e.%m.%Y from %-d.%-m.%Y.
diff --git a/localedata/charmaps/BRF b/localedata/charmaps/BRF
new file mode 100644
index 0000000000..6b06f7164a
--- /dev/null
+++ b/localedata/charmaps/BRF
@@ -0,0 +1,108 @@
+<code_set_name> BRF
+<comment_char> %
+<escape_char> /
+% version: 1.0
+%  source: Samuel Thibault <samuel.thibault@ens-lyon.org>
+
+CHARMAP
+<U0000>     /x00         NULL (NUL)
+<U0001>     /x01         START OF HEADING (SOH)
+<U0002>     /x02         START OF TEXT (STX)
+<U0003>     /x03         END OF TEXT (ETX)
+<U0004>     /x04         END OF TRANSMISSION (EOT)
+<U0005>     /x05         ENQUIRY (ENQ)
+<U0006>     /x06         ACKNOWLEDGE (ACK)
+<U0007>     /x07         BELL (BEL)
+<U0008>     /x08         BACKSPACE (BS)
+<U0009>     /x09         CHARACTER TABULATION (HT)
+<U000A>     /x0a         LINE FEED (LF)
+<U000B>     /x0b         LINE TABULATION (VT)
+<U000C>     /x0c         FORM FEED (FF)
+<U000D>     /x0d         CARRIAGE RETURN (CR)
+<U000E>     /x0e         SHIFT OUT (SO)
+<U000F>     /x0f         SHIFT IN (SI)
+<U0010>     /x10         DATALINK ESCAPE (DLE)
+<U0011>     /x11         DEVICE CONTROL ONE (DC1)
+<U0012>     /x12         DEVICE CONTROL TWO (DC2)
+<U0013>     /x13         DEVICE CONTROL THREE (DC3)
+<U0014>     /x14         DEVICE CONTROL FOUR (DC4)
+<U0015>     /x15         NEGATIVE ACKNOWLEDGE (NAK)
+<U0016>     /x16         SYNCHRONOUS IDLE (SYN)
+<U0017>     /x17         END OF TRANSMISSION BLOCK (ETB)
+<U0018>     /x18         CANCEL (CAN)
+<U0019>     /x19         END OF MEDIUM (EM)
+<U001A>     /x1a         SUBSTITUTE (SUB)
+<U001B>     /x1b         ESCAPE (ESC)
+<U001C>     /x1c         FILE SEPARATOR (IS4)
+<U001D>     /x1d         GROUP SEPARATOR (IS3)
+<U001E>     /x1e         RECORD SEPARATOR (IS2)
+<U001F>     /x1f         UNIT SEPARATOR (IS1)
+<U2800>     /x20         BRAILLE PATTERN BLANK
+<U282E>     /x21         BRAILLE PATTERN DOTS-2346
+<U2810>     /x22         BRAILLE PATTERN DOTS-5
+<U283C>     /x23         BRAILLE PATTERN DOTS-3456
+<U282B>     /x24         BRAILLE PATTERN DOTS-1246
+<U2829>     /x25         BRAILLE PATTERN DOTS-146
+<U282F>     /x26         BRAILLE PATTERN DOTS-12346
+<U2804>     /x27         BRAILLE PATTERN DOTS-3
+<U2837>     /x28         BRAILLE PATTERN DOTS-12356
+<U283E>     /x29         BRAILLE PATTERN DOTS-23456
+<U2821>     /x2a         BRAILLE PATTERN DOTS-16
+<U282C>     /x2b         BRAILLE PATTERN DOTS-346
+<U2820>     /x2c         BRAILLE PATTERN DOTS-6
+<U2824>     /x2d         BRAILLE PATTERN DOTS-36
+<U2828>     /x2e         BRAILLE PATTERN DOTS-46
+<U280C>     /x2f         BRAILLE PATTERN DOTS-34
+<U2834>     /x30         BRAILLE PATTERN DOTS-356
+<U2802>     /x31         BRAILLE PATTERN DOTS-2
+<U2806>     /x32         BRAILLE PATTERN DOTS-23
+<U2812>     /x33         BRAILLE PATTERN DOTS-25
+<U2832>     /x34         BRAILLE PATTERN DOTS-256
+<U2822>     /x35         BRAILLE PATTERN DOTS-26
+<U2816>     /x36         BRAILLE PATTERN DOTS-235
+<U2836>     /x37         BRAILLE PATTERN DOTS-2356
+<U2826>     /x38         BRAILLE PATTERN DOTS-236
+<U2814>     /x39         BRAILLE PATTERN DOTS-35
+<U2831>     /x3a         BRAILLE PATTERN DOTS-156
+<U2830>     /x3b         BRAILLE PATTERN DOTS-56
+<U2823>     /x3c         BRAILLE PATTERN DOTS-126
+<U283F>     /x3d         BRAILLE PATTERN DOTS-123456
+<U281C>     /x3e         BRAILLE PATTERN DOTS-345
+<U2839>     /x3f         BRAILLE PATTERN DOTS-1456
+<U2808>     /x40         BRAILLE PATTERN DOTS-4
+<U2801>     /x41         BRAILLE PATTERN DOTS-1
+<U2803>     /x42         BRAILLE PATTERN DOTS-12
+<U2809>     /x43         BRAILLE PATTERN DOTS-14
+<U2819>     /x44         BRAILLE PATTERN DOTS-145
+<U2811>     /x45         BRAILLE PATTERN DOTS-15
+<U280B>     /x46         BRAILLE PATTERN DOTS-124
+<U281B>     /x47         BRAILLE PATTERN DOTS-1245
+<U2813>     /x48         BRAILLE PATTERN DOTS-125
+<U280A>     /x49         BRAILLE PATTERN DOTS-24
+<U281A>     /x4a         BRAILLE PATTERN DOTS-245
+<U2805>     /x4b         BRAILLE PATTERN DOTS-13
+<U2807>     /x4c         BRAILLE PATTERN DOTS-123
+<U280D>     /x4d         BRAILLE PATTERN DOTS-134
+<U281D>     /x4e         BRAILLE PATTERN DOTS-1345
+<U2815>     /x4f         BRAILLE PATTERN DOTS-135
+<U280F>     /x50         BRAILLE PATTERN DOTS-1234
+<U281F>     /x51         BRAILLE PATTERN DOTS-12345
+<U2817>     /x52         BRAILLE PATTERN DOTS-1235
+<U280E>     /x53         BRAILLE PATTERN DOTS-234
+<U281E>     /x54         BRAILLE PATTERN DOTS-2345
+<U2825>     /x55         BRAILLE PATTERN DOTS-136
+<U2827>     /x56         BRAILLE PATTERN DOTS-1236
+<U283A>     /x57         BRAILLE PATTERN DOTS-2456
+<U282D>     /x58         BRAILLE PATTERN DOTS-1346
+<U283D>     /x59         BRAILLE PATTERN DOTS-13456
+<U2835>     /x5a         BRAILLE PATTERN DOTS-1356
+<U282A>     /x5b         BRAILLE PATTERN DOTS-246
+<U2833>     /x5c         BRAILLE PATTERN DOTS-1256
+<U283B>     /x5d         BRAILLE PATTERN DOTS-12456
+<U2818>     /x5e         BRAILLE PATTERN DOTS-45
+<U2838>     /x5f         BRAILLE PATTERN DOTS-456
+END CHARMAP
+
+WIDTH
+<U2800>...<U283F>	1
+END WIDTH
diff --git a/misc/hsearch_r.c b/misc/hsearch_r.c
index b03c12ce0b..cb4d67466b 100644
--- a/misc/hsearch_r.c
+++ b/misc/hsearch_r.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993,1995,1996,1997,2002,2005 Free Software Foundation, Inc.
+/* Copyright (C) 1993,1995-1997,2002,2005,2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1993.
 
@@ -110,9 +110,8 @@ hdestroy_r (htab)
       return;
     }
 
-  if (htab->table != NULL)
-    /* free used memory */
-    free (htab->table);
+  /* Free used memory.  */
+  free (htab->table);
 
   /* the sign for an existing table is an value != NULL in htable */
   htab->table = NULL;
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 842a04f9f0..9ee7f8d47d 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,10 @@
+2007-01-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* tst-initializers1.c: We want to test the initializers as seen
+	outside of libc, so undefined _LIBC.
+
+	* pthread_join.c (cleanup): Avoid warning.
+
 2007-01-17  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
diff --git a/nptl/pthread_join.c b/nptl/pthread_join.c
index c88d85b52f..6a87a8b329 100644
--- a/nptl/pthread_join.c
+++ b/nptl/pthread_join.c
@@ -30,8 +30,8 @@ cleanup (void *arg)
   /* If we already changed the waiter ID, reset it.  The call cannot
      fail for any reason but the thread not having done that yet so
      there is no reason for a loop.  */
-  atomic_compare_and_exchange_bool_acq ((struct pthread **) arg, NULL,
-					THREAD_SELF);
+  (void) atomic_compare_and_exchange_bool_acq ((struct pthread **) arg, NULL,
+					       THREAD_SELF);
 }
 
 
diff --git a/nptl/tst-initializers1.c b/nptl/tst-initializers1.c
index ccd27286e8..eacee35c61 100644
--- a/nptl/tst-initializers1.c
+++ b/nptl/tst-initializers1.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
 
@@ -17,6 +17,9 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+/* We test the code undef conditions outside of glibc.  */
+#undef _LIBC
+
 #include <pthread.h>
 
 pthread_mutex_t mtx_normal = PTHREAD_MUTEX_INITIALIZER;
diff --git a/nscd/connections.c b/nscd/connections.c
index 88b44c3034..4e01b3182c 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -1430,7 +1430,6 @@ nscd_run (void *p)
 
       /* It should not be possible to crash the nscd with a silly
 	 request (i.e., a terribly large key).  We limit the size to 1kb.  */
-#define MAXKEYLEN 1024
       if (__builtin_expect (req.key_len, 1) < 0
 	  || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
 	{
diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h
index 7702f590bd..3c9688fd30 100644
--- a/nscd/nscd-client.h
+++ b/nscd/nscd-client.h
@@ -44,6 +44,9 @@
 /* Path for the configuration file.  */
 #define _PATH_NSCDCONF	 "/etc/nscd.conf"
 
+/* Maximu allowed length for the key.  */
+#define MAXKEYLEN 1024
+
 
 /* Available services.  */
 typedef enum
@@ -323,10 +326,10 @@ static inline int __nscd_drop_map_ref (struct mapped_database *map,
 
 
 /* Search the mapped database.  */
-extern const struct datahead *__nscd_cache_search (request_type type,
-						   const char *key,
-						   size_t keylen,
-						   const struct mapped_database *mapped);
+extern struct datahead *__nscd_cache_search (request_type type,
+					     const char *key,
+					     size_t keylen,
+					     const struct mapped_database *mapped);
 
 /* Wrappers around read, readv and write that only read/write less than LEN
    bytes on error or EOF.  */
diff --git a/nscd/nscd_getai.c b/nscd/nscd_getai.c
index b59c31ea26..5df32dc6dc 100644
--- a/nscd/nscd_getai.c
+++ b/nscd/nscd_getai.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -42,6 +42,7 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
 {
   size_t keylen = strlen (key) + 1;
   int gc_cycle;
+  int nretries = 0;
 
   /* If the mapping is available, try to search there instead of
      communicating with the nscd.  */
@@ -50,49 +51,53 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
 			       &gc_cycle);
 
  retry:;
-  const ai_response_header *ai_resp = NULL;
   struct nscd_ai_result *resultbuf = NULL;
   const char *recend = (const char *) ~UINTMAX_C (0);
   char *respdata = NULL;
   int retval = -1;
   int sock = -1;
+  ai_response_header ai_resp;
 
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (GETAI, key, keylen,
-							  mapped);
+      struct datahead *found = __nscd_cache_search (GETAI, key, keylen,
+						    mapped);
       if (found != NULL)
 	{
-	  ai_resp = &found->data[0].aidata;
-	  respdata = (char *) (ai_resp + 1);
+	  respdata = (char *) (&found->data[0].aidata + 1);
+	  ai_resp = found->data[0].aidata;
 	  recend = (const char *) found->data + found->recsize;
+	  /* Now check if we can trust ai_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
 	}
     }
 
   /* If we do not have the cache mapped, try to get the data over the
      socket.  */
-  ai_response_header ai_resp_mem;
-  if (ai_resp == NULL)
+  if (respdata == NULL)
     {
-      sock = __nscd_open_socket (key, keylen, GETAI, &ai_resp_mem,
-				 sizeof (ai_resp_mem));
+      sock = __nscd_open_socket (key, keylen, GETAI, &ai_resp,
+				 sizeof (ai_resp));
       if (sock == -1)
 	{
 	  /* nscd not running or wrong version.  */
 	  __nss_not_use_nscd_hosts = 1;
 	  goto out;
 	}
-
-      ai_resp = &ai_resp_mem;
     }
 
-  if (ai_resp->found == 1)
+  if (ai_resp.found == 1)
     {
-      size_t datalen = ai_resp->naddrs + ai_resp->addrslen + ai_resp->canonlen;
+      size_t datalen = ai_resp.naddrs + ai_resp.addrslen + ai_resp.canonlen;
 
-      /* This check is really only affects the case where the data
+      /* This check really only affects the case where the data
 	 comes from the mapped cache.  */
-      if ((char *) (ai_resp + 1) + datalen > recend)
+      if (respdata + datalen > recend)
 	{
 	  assert (sock == -1);
 	  goto out;
@@ -108,10 +113,10 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
 	}
 
       /* Set up the data structure, including pointers.  */
-      resultbuf->naddrs = ai_resp->naddrs;
+      resultbuf->naddrs = ai_resp.naddrs;
       resultbuf->addrs = (char *) (resultbuf + 1);
-      resultbuf->family = (uint8_t *) (resultbuf->addrs + ai_resp->addrslen);
-      if (ai_resp->canonlen != 0)
+      resultbuf->family = (uint8_t *) (resultbuf->addrs + ai_resp.addrslen);
+      if (ai_resp.canonlen != 0)
 	resultbuf->canon = (char *) (resultbuf->family + resultbuf->naddrs);
       else
 	resultbuf->canon = NULL;
@@ -137,10 +142,13 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
 
 	  /* Try to detect corrupt databases.  */
 	  if (resultbuf->canon != NULL
-	      && resultbuf->canon[ai_resp->canonlen - 1] != '\0')
+	      && resultbuf->canon[ai_resp.canonlen - 1] != '\0')
 	    /* We cannot use the database.  */
 	    {
-	      free (resultbuf);
+	      if (mapped->head->gc_cycle != gc_cycle)
+		retval = -2;
+	      else
+		free (resultbuf);
 	      goto out_close;
 	    }
 
@@ -150,7 +158,7 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
     }
   else
     {
-      if (__builtin_expect (ai_resp->found == -1, 0))
+      if (__builtin_expect (ai_resp.found == -1, 0))
 	{
 	  /* The daemon does not cache this database.  */
 	  __nss_not_use_nscd_hosts = 1;
@@ -158,7 +166,7 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
 	}
 
       /* Store the error number.  */
-      *h_errnop = ai_resp->error;
+      *h_errnop = ai_resp.error;
 
       /* The `errno' to some value != ERANGE.  */
       __set_errno (ENOENT);
@@ -170,22 +178,25 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      *result = NULL;
-      free (resultbuf);
-
-      goto retry;
+      if (retval != -1)
+	{
+	  *result = NULL;
+	  free (resultbuf);
+	  goto retry;
+	}
     }
 
   return retval;
diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c
index 922b906c19..fc036f2888 100644
--- a/nscd/nscd_getgr_r.c
+++ b/nscd/nscd_getgr_r.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998-2000, 2002-2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2000, 2002-2005, 2006, 2007
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@uni-paderborn.de>, 1998.
 
@@ -88,6 +89,7 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
 	      struct group **result)
 {
   int gc_cycle;
+  int nretries = 0;
   const uint32_t *len = NULL;
   size_t lensize = 0;
 
@@ -97,55 +99,59 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
 						       &__gr_map_handle,
 						       &gc_cycle);
  retry:;
-  const gr_response_header *gr_resp = NULL;
   const char *gr_name = NULL;
   size_t gr_name_len = 0;
   int retval = -1;
   const char *recend = (const char *) ~UINTMAX_C (0);
+  gr_response_header gr_resp;
 
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (type, key, keylen,
-							  mapped);
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
       if (found != NULL)
 	{
-	  gr_resp = &found->data[0].grdata;
-	  len = (const uint32_t *) (gr_resp + 1);
-	  /* The alignment is always sufficient.  */
-	  assert (((uintptr_t) len & (__alignof__ (*len) - 1)) == 0);
+	  len = (const uint32_t *) (&found->data[0].grdata + 1);
+	  gr_resp = found->data[0].grdata;
 	  gr_name = ((const char *) len
-		     + gr_resp->gr_mem_cnt * sizeof (uint32_t));
-	  gr_name_len = gr_resp->gr_name_len + gr_resp->gr_passwd_len;
+		     + gr_resp.gr_mem_cnt * sizeof (uint32_t));
+	  gr_name_len = gr_resp.gr_name_len + gr_resp.gr_passwd_len;
 	  recend = (const char *) found->data + found->recsize;
+	  /* Now check if we can trust gr_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
+
+	  /* The alignment is always sufficient, unless GC is in progress.  */
+	  assert (((uintptr_t) len & (__alignof__ (*len) - 1)) == 0);
 	}
     }
 
-  gr_response_header gr_resp_mem;
   int sock = -1;
-  if (gr_resp == NULL)
+  if (gr_name == NULL)
     {
-      sock = __nscd_open_socket (key, keylen, type, &gr_resp_mem,
-				 sizeof (gr_resp_mem));
+      sock = __nscd_open_socket (key, keylen, type, &gr_resp,
+				 sizeof (gr_resp));
       if (sock == -1)
 	{
 	  __nss_not_use_nscd_group = 1;
 	  goto out;
 	}
-
-      gr_resp = &gr_resp_mem;
     }
 
   /* No value found so far.  */
   *result = NULL;
 
-  if (__builtin_expect (gr_resp->found == -1, 0))
+  if (__builtin_expect (gr_resp.found == -1, 0))
     {
       /* The daemon does not cache this database.  */
       __nss_not_use_nscd_group = 1;
       goto out_close;
     }
 
-  if (gr_resp->found == 1)
+  if (gr_resp.found == 1)
     {
       struct iovec vec[2];
       char *p = buffer;
@@ -157,8 +163,8 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
 	 align the pointer.  */
       align = ((__alignof__ (char *) - (p - ((char *) 0)))
 	       & (__alignof__ (char *) - 1));
-      total_len = (align + (1 + gr_resp->gr_mem_cnt) * sizeof (char *)
-		   + gr_resp->gr_name_len + gr_resp->gr_passwd_len);
+      total_len = (align + (1 + gr_resp.gr_mem_cnt) * sizeof (char *)
+		   + gr_resp.gr_name_len + gr_resp.gr_passwd_len);
       if (__builtin_expect (buflen < total_len, 0))
 	{
 	no_room:
@@ -170,16 +176,16 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
 
       p += align;
       resultbuf->gr_mem = (char **) p;
-      p += (1 + gr_resp->gr_mem_cnt) * sizeof (char *);
+      p += (1 + gr_resp.gr_mem_cnt) * sizeof (char *);
 
       /* Set pointers for strings.  */
       resultbuf->gr_name = p;
-      p += gr_resp->gr_name_len;
+      p += gr_resp.gr_name_len;
       resultbuf->gr_passwd = p;
-      p += gr_resp->gr_passwd_len;
+      p += gr_resp.gr_passwd_len;
 
       /* Fill in what we know now.  */
-      resultbuf->gr_gid = gr_resp->gr_gid;
+      resultbuf->gr_gid = gr_resp.gr_gid;
 
       /* Read the length information, group name, and password.  */
       if (gr_name == NULL)
@@ -187,17 +193,17 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
 	  /* Allocate array to store lengths.  */
 	  if (lensize == 0)
 	    {
-	      lensize = gr_resp->gr_mem_cnt * sizeof (uint32_t);
+	      lensize = gr_resp.gr_mem_cnt * sizeof (uint32_t);
 	      len = (uint32_t *) alloca (lensize);
 	    }
-	  else if (gr_resp->gr_mem_cnt * sizeof (uint32_t) > lensize)
+	  else if (gr_resp.gr_mem_cnt * sizeof (uint32_t) > lensize)
 	    len = extend_alloca (len, lensize,
-				 gr_resp->gr_mem_cnt * sizeof (uint32_t));
+				 gr_resp.gr_mem_cnt * sizeof (uint32_t));
 
 	  vec[0].iov_base = (void *) len;
-	  vec[0].iov_len = gr_resp->gr_mem_cnt * sizeof (uint32_t);
+	  vec[0].iov_len = gr_resp.gr_mem_cnt * sizeof (uint32_t);
 	  vec[1].iov_base = resultbuf->gr_name;
-	  vec[1].iov_len = gr_resp->gr_name_len + gr_resp->gr_passwd_len;
+	  vec[1].iov_len = gr_resp.gr_name_len + gr_resp.gr_passwd_len;
 	  total_len = vec[0].iov_len + vec[1].iov_len;
 
 	  /* Get this data.  */
@@ -209,14 +215,14 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
 	/* We already have the data.  Just copy the group name and
 	   password.  */
 	memcpy (resultbuf->gr_name, gr_name,
-		gr_resp->gr_name_len + gr_resp->gr_passwd_len);
+		gr_resp.gr_name_len + gr_resp.gr_passwd_len);
 
       /* Clear the terminating entry.  */
-      resultbuf->gr_mem[gr_resp->gr_mem_cnt] = NULL;
+      resultbuf->gr_mem[gr_resp.gr_mem_cnt] = NULL;
 
       /* Prepare reading the group members.  */
       total_len = 0;
-      for (cnt = 0; cnt < gr_resp->gr_mem_cnt; ++cnt)
+      for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt)
 	{
 	  resultbuf->gr_mem[cnt] = p;
 	  total_len += len[cnt];
@@ -224,9 +230,25 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
 	}
 
       if (__builtin_expect (gr_name + gr_name_len + total_len > recend, 0))
-	goto out_close;
+	{
+	  /* len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (gr_name != NULL && mapped->head->gc_cycle != gc_cycle)
+	    retval = -2;
+	  goto out_close;
+	}
       if (__builtin_expect (total_len > buflen, 0))
-	goto no_room;
+	{
+	  /* len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (gr_name != NULL && mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out_close;
+	    }
+	  else
+	    goto no_room;
+	}
 
       retval = 0;
       if (gr_name == NULL)
@@ -248,14 +270,14 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
 
 	  /* Try to detect corrupt databases.  */
 	  if (resultbuf->gr_name[gr_name_len - 1] != '\0'
-	      || resultbuf->gr_passwd[gr_resp->gr_passwd_len - 1] != '\0'
-	      || ({for (cnt = 0; cnt < gr_resp->gr_mem_cnt; ++cnt)
+	      || resultbuf->gr_passwd[gr_resp.gr_passwd_len - 1] != '\0'
+	      || ({for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt)
 		     if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0')
 		       break;
-	  	   cnt < gr_resp->gr_mem_cnt; }))
+	  	   cnt < gr_resp.gr_mem_cnt; }))
 	    {
 	      /* We cannot use the database.  */
-	      retval = -1;
+	      retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1;
 	      goto out_close;
 	    }
 
@@ -274,19 +296,21 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      goto retry;
+      if (retval != -1)
+	goto retry;
     }
 
   return retval;
diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c
index e83e4823ea..03b73a4a47 100644
--- a/nscd/nscd_gethst_r.c
+++ b/nscd/nscd_gethst_r.c
@@ -113,7 +113,6 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 			       &gc_cycle);
 
  retry:;
-  const hst_response_header *hst_resp = NULL;
   const char *h_name = NULL;
   const uint32_t *aliases_len = NULL;
   const char *addr_list = NULL;
@@ -121,18 +120,27 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
   int retval = -1;
   const char *recend = (const char *) ~UINTMAX_C (0);
   int sock = -1;
+  hst_response_header hst_resp;
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (type, key, keylen,
-							  mapped);
+      /* No const qualifier, as it can change during garbage collection.  */
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
       if (found != NULL)
 	{
-	  hst_resp = &found->data[0].hstdata;
-	  h_name = (char *) (hst_resp + 1);
-	  aliases_len = (uint32_t *) (h_name + hst_resp->h_name_len);
+	  h_name = (char *) (&found->data[0].hstdata + 1);
+	  hst_resp = found->data[0].hstdata;
+	  aliases_len = (uint32_t *) (h_name + hst_resp.h_name_len);
 	  addr_list = ((char *) aliases_len
-		       + hst_resp->h_aliases_cnt * sizeof (uint32_t));
-	  addr_list_len = hst_resp->h_addr_list_cnt * INADDRSZ;
+		       + hst_resp.h_aliases_cnt * sizeof (uint32_t));
+	  addr_list_len = hst_resp.h_addr_list_cnt * INADDRSZ;
+	  recend = (const char *) found->data + found->recsize;
+	  /* Now check if we can trust hst_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
 
 #ifndef _STRING_ARCH_unaligned
 	  /* The aliases_len array in the mapped database might very
@@ -142,51 +150,47 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 	  if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
 	      != 0)
 	    {
-	      uint32_t *tmp = alloca (hst_resp->h_aliases_cnt
+	      uint32_t *tmp = alloca (hst_resp.h_aliases_cnt
 				      * sizeof (uint32_t));
 	      aliases_len = memcpy (tmp, aliases_len,
-				    hst_resp->h_aliases_cnt
+				    hst_resp.h_aliases_cnt
 				    * sizeof (uint32_t));
 	    }
 #endif
 	  if (type != GETHOSTBYADDR && type != GETHOSTBYNAME)
 	    {
-	      if (hst_resp->h_length == INADDRSZ)
+	      if (hst_resp.h_length == INADDRSZ)
 		addr_list += addr_list_len;
-	      addr_list_len = hst_resp->h_addr_list_cnt * IN6ADDRSZ;
+	      addr_list_len = hst_resp.h_addr_list_cnt * IN6ADDRSZ;
 	    }
-	  recend = (const char *) found->data + found->recsize;
 	  if (__builtin_expect ((const char *) addr_list + addr_list_len
 				> recend, 0))
-	    goto out_close;
+	    goto out;
 	}
     }
 
-  hst_response_header hst_resp_mem;
-  if (hst_resp == NULL)
+  if (h_name == NULL)
     {
-      sock = __nscd_open_socket (key, keylen, type, &hst_resp_mem,
-				 sizeof (hst_resp_mem));
+      sock = __nscd_open_socket (key, keylen, type, &hst_resp,
+				 sizeof (hst_resp));
       if (sock == -1)
 	{
 	  __nss_not_use_nscd_hosts = 1;
 	  goto out;
 	}
-
-      hst_resp = &hst_resp_mem;
     }
 
   /* No value found so far.  */
   *result = NULL;
 
-  if (__builtin_expect (hst_resp->found == -1, 0))
+  if (__builtin_expect (hst_resp.found == -1, 0))
     {
       /* The daemon does not cache this database.  */
       __nss_not_use_nscd_hosts = 1;
       goto out_close;
     }
 
-  if (hst_resp->found == 1)
+  if (hst_resp.found == 1)
     {
       char *cp = buffer;
       uintptr_t align1;
@@ -201,15 +205,15 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 	 align the pointer and the base of the h_addr_list pointers.  */
       align1 = ((__alignof__ (char *) - (cp - ((char *) 0)))
 		& (__alignof__ (char *) - 1));
-      align2 = ((__alignof__ (char *) - ((cp + align1 + hst_resp->h_name_len)
+      align2 = ((__alignof__ (char *) - ((cp + align1 + hst_resp.h_name_len)
 					 - ((char *) 0)))
 		& (__alignof__ (char *) - 1));
-      if (buflen < (align1 + hst_resp->h_name_len + align2
-		    + ((hst_resp->h_aliases_cnt + hst_resp->h_addr_list_cnt
+      if (buflen < (align1 + hst_resp.h_name_len + align2
+		    + ((hst_resp.h_aliases_cnt + hst_resp.h_addr_list_cnt
 			+ 2)
 		       * sizeof (char *))
-		    + hst_resp->h_addr_list_cnt * (type == AF_INET
-						   ? INADDRSZ : IN6ADDRSZ)))
+		    + hst_resp.h_addr_list_cnt * (type == AF_INET
+						  ? INADDRSZ : IN6ADDRSZ)))
 	{
 	no_room:
 	  *h_errnop = NETDB_INTERNAL;
@@ -221,12 +225,12 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 
       /* Prepare the result as far as we can.  */
       resultbuf->h_aliases = (char **) cp;
-      cp += (hst_resp->h_aliases_cnt + 1) * sizeof (char *);
+      cp += (hst_resp.h_aliases_cnt + 1) * sizeof (char *);
       resultbuf->h_addr_list = (char **) cp;
-      cp += (hst_resp->h_addr_list_cnt + 1) * sizeof (char *);
+      cp += (hst_resp.h_addr_list_cnt + 1) * sizeof (char *);
 
       resultbuf->h_name = cp;
-      cp += hst_resp->h_name_len + align2;
+      cp += hst_resp.h_name_len + align2;
 
       if (type == GETHOSTBYADDR || type == GETHOSTBYNAME)
 	{
@@ -238,7 +242,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 	  resultbuf->h_addrtype = AF_INET6;
 	  resultbuf->h_length = IN6ADDRSZ;
 	}
-      for (cnt = 0; cnt < hst_resp->h_addr_list_cnt; ++cnt)
+      for (cnt = 0; cnt < hst_resp.h_addr_list_cnt; ++cnt)
 	{
 	  resultbuf->h_addr_list[cnt] = cp;
 	  cp += resultbuf->h_length;
@@ -250,47 +254,47 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 	  struct iovec vec[4];
 
 	  vec[0].iov_base = resultbuf->h_name;
-	  vec[0].iov_len = hst_resp->h_name_len;
-	  total_len = hst_resp->h_name_len;
+	  vec[0].iov_len = hst_resp.h_name_len;
+	  total_len = hst_resp.h_name_len;
 	  n = 1;
 
-	  if (hst_resp->h_aliases_cnt > 0)
+	  if (hst_resp.h_aliases_cnt > 0)
 	    {
-	      aliases_len = alloca (hst_resp->h_aliases_cnt
+	      aliases_len = alloca (hst_resp.h_aliases_cnt
 				    * sizeof (uint32_t));
 	      vec[n].iov_base = (void *) aliases_len;
-	      vec[n].iov_len = hst_resp->h_aliases_cnt * sizeof (uint32_t);
+	      vec[n].iov_len = hst_resp.h_aliases_cnt * sizeof (uint32_t);
 
-	      total_len += hst_resp->h_aliases_cnt * sizeof (uint32_t);
+	      total_len += hst_resp.h_aliases_cnt * sizeof (uint32_t);
 	      ++n;
 	    }
 
 	  if (type == GETHOSTBYADDR || type == GETHOSTBYNAME)
 	    {
 	      vec[n].iov_base = resultbuf->h_addr_list[0];
-	      vec[n].iov_len = hst_resp->h_addr_list_cnt * INADDRSZ;
+	      vec[n].iov_len = hst_resp.h_addr_list_cnt * INADDRSZ;
 
-	      total_len += hst_resp->h_addr_list_cnt * INADDRSZ;
+	      total_len += hst_resp.h_addr_list_cnt * INADDRSZ;
 
 	      ++n;
 	    }
 	  else
 	    {
-	      if (hst_resp->h_length == INADDRSZ)
+	      if (hst_resp.h_length == INADDRSZ)
 		{
-		  ignore = alloca (hst_resp->h_addr_list_cnt * INADDRSZ);
+		  ignore = alloca (hst_resp.h_addr_list_cnt * INADDRSZ);
 		  vec[n].iov_base = ignore;
-		  vec[n].iov_len = hst_resp->h_addr_list_cnt * INADDRSZ;
+		  vec[n].iov_len = hst_resp.h_addr_list_cnt * INADDRSZ;
 
-		  total_len += hst_resp->h_addr_list_cnt * INADDRSZ;
+		  total_len += hst_resp.h_addr_list_cnt * INADDRSZ;
 
 		  ++n;
 		}
 
 	      vec[n].iov_base = resultbuf->h_addr_list[0];
-	      vec[n].iov_len = hst_resp->h_addr_list_cnt * IN6ADDRSZ;
+	      vec[n].iov_len = hst_resp.h_addr_list_cnt * IN6ADDRSZ;
 
-	      total_len += hst_resp->h_addr_list_cnt * IN6ADDRSZ;
+	      total_len += hst_resp.h_addr_list_cnt * IN6ADDRSZ;
 
 	      ++n;
 	    }
@@ -300,13 +304,13 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 	}
       else
 	{
-	  memcpy (resultbuf->h_name, h_name, hst_resp->h_name_len);
+	  memcpy (resultbuf->h_name, h_name, hst_resp.h_name_len);
 	  memcpy (resultbuf->h_addr_list[0], addr_list, addr_list_len);
 	}
 
       /*  Now we also can read the aliases.  */
       total_len = 0;
-      for (cnt = 0; cnt < hst_resp->h_aliases_cnt; ++cnt)
+      for (cnt = 0; cnt < hst_resp.h_aliases_cnt; ++cnt)
 	{
 	  resultbuf->h_aliases[cnt] = cp;
 	  cp += aliases_len[cnt];
@@ -316,10 +320,25 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 
       if (__builtin_expect ((const char *) addr_list + addr_list_len
 			    + total_len > recend, 0))
-	goto out_close;
+	{
+	  /* aliases_len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (addr_list != NULL && mapped->head->gc_cycle != gc_cycle)
+	    retval = -2;
+	  goto out_close;
+	}
       /* See whether this would exceed the buffer capacity.  */
       if (__builtin_expect (cp > buffer + buflen, 0))
-	goto no_room;
+	{
+	  /* aliases_len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (addr_list != NULL && mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out_close;
+	    }
+	  goto no_room;
+	}
 
       /* And finally read the aliases.  */
       if (addr_list == NULL)
@@ -338,14 +357,18 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 		  (const char *) addr_list + addr_list_len, total_len);
 
 	  /* Try to detect corrupt databases.  */
-	  if (resultbuf->h_name[hst_resp->h_name_len - 1] != '\0'
-	      || ({for (cnt = 0; cnt < hst_resp->h_aliases_cnt; ++cnt)
+	  if (resultbuf->h_name[hst_resp.h_name_len - 1] != '\0'
+	      || ({for (cnt = 0; cnt < hst_resp.h_aliases_cnt; ++cnt)
 		     if (resultbuf->h_aliases[cnt][aliases_len[cnt] - 1]
 			 != '\0')
 		       break;
-		   cnt < hst_resp->h_aliases_cnt; }))
-	    /* We cannot use the database.  */
-	    goto out_close;
+		   cnt < hst_resp.h_aliases_cnt; }))
+	    {
+	      /* We cannot use the database.  */
+	      if (mapped->head->gc_cycle != gc_cycle)
+		retval = -2;
+	      goto out_close;
+	    }
 
 	  retval = 0;
 	  *result = resultbuf;
@@ -354,7 +377,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
   else
     {
       /* Store the error number.  */
-      *h_errnop = hst_resp->error;
+      *h_errnop = hst_resp.error;
 
       /* The `errno' to some value != ERANGE.  */
       __set_errno (ENOENT);
@@ -366,19 +389,21 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0 || ++nretries == 5)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      goto retry;
+      if (retval != -1)
+	goto retry;
     }
 
   return retval;
diff --git a/nscd/nscd_getpw_r.c b/nscd/nscd_getpw_r.c
index e8e4d7364f..b84baa1a66 100644
--- a/nscd/nscd_getpw_r.c
+++ b/nscd/nscd_getpw_r.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998, 1999, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2003, 2004, 2005, 2007
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@uni-paderborn.de>, 1998.
 
@@ -88,76 +89,81 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type,
 	      struct passwd **result)
 {
   int gc_cycle;
+  int nretries = 0;
+
   /* If the mapping is available, try to search there instead of
      communicating with the nscd.  */
   struct mapped_database *mapped;
   mapped = __nscd_get_map_ref (GETFDPW, "passwd", &map_handle, &gc_cycle);
 
  retry:;
-  const pw_response_header *pw_resp = NULL;
   const char *pw_name = NULL;
   int retval = -1;
   const char *recend = (const char *) ~UINTMAX_C (0);
+  pw_response_header pw_resp;
 
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (type, key, keylen,
-							  mapped);
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
       if (found != NULL)
 	{
-	  pw_resp = &found->data[0].pwdata;
-	  pw_name = (const char *) (pw_resp + 1);
+	  pw_name = (const char *) (&found->data[0].pwdata + 1);
+	  pw_resp = found->data[0].pwdata;
 	  recend = (const char *) found->data + found->recsize;
+	  /* Now check if we can trust pw_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
 	}
     }
 
-  pw_response_header pw_resp_mem;
   int sock = -1;
-  if (pw_resp == NULL)
+  if (pw_name == NULL)
     {
-      sock = __nscd_open_socket (key, keylen, type, &pw_resp_mem,
-				 sizeof (pw_resp_mem));
+      sock = __nscd_open_socket (key, keylen, type, &pw_resp,
+				 sizeof (pw_resp));
       if (sock == -1)
 	{
 	  __nss_not_use_nscd_passwd = 1;
 	  goto out;
 	}
-
-      pw_resp = &pw_resp_mem;
     }
 
   /* No value found so far.  */
   *result = NULL;
 
-  if (__builtin_expect (pw_resp->found == -1, 0))
+  if (__builtin_expect (pw_resp.found == -1, 0))
     {
       /* The daemon does not cache this database.  */
       __nss_not_use_nscd_passwd = 1;
       goto out_close;
     }
 
-  if (pw_resp->found == 1)
+  if (pw_resp.found == 1)
     {
       /* Set the information we already have.  */
-      resultbuf->pw_uid = pw_resp->pw_uid;
-      resultbuf->pw_gid = pw_resp->pw_gid;
+      resultbuf->pw_uid = pw_resp.pw_uid;
+      resultbuf->pw_gid = pw_resp.pw_gid;
 
       char *p = buffer;
       /* get pw_name */
       resultbuf->pw_name = p;
-      p += pw_resp->pw_name_len;
+      p += pw_resp.pw_name_len;
       /* get pw_passwd */
       resultbuf->pw_passwd = p;
-      p += pw_resp->pw_passwd_len;
+      p += pw_resp.pw_passwd_len;
       /* get pw_gecos */
       resultbuf->pw_gecos = p;
-      p += pw_resp->pw_gecos_len;
+      p += pw_resp.pw_gecos_len;
       /* get pw_dir */
       resultbuf->pw_dir = p;
-      p += pw_resp->pw_dir_len;
+      p += pw_resp.pw_dir_len;
       /* get pw_pshell */
       resultbuf->pw_shell = p;
-      p += pw_resp->pw_shell_len;
+      p += pw_resp.pw_shell_len;
 
       ssize_t total = p - buffer;
       if (__builtin_expect (pw_name + total > recend, 0))
@@ -189,14 +195,14 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type,
 	  memcpy (resultbuf->pw_name, pw_name, total);
 
 	  /* Try to detect corrupt databases.  */
-	  if (resultbuf->pw_name[pw_resp->pw_name_len - 1] != '\0'
-	      || resultbuf->pw_passwd[pw_resp->pw_passwd_len - 1] != '\0'
-	      || resultbuf->pw_gecos[pw_resp->pw_gecos_len - 1] != '\0'
-	      || resultbuf->pw_dir[pw_resp->pw_dir_len - 1] != '\0'
-	      || resultbuf->pw_shell[pw_resp->pw_shell_len - 1] != '\0')
+	  if (resultbuf->pw_name[pw_resp.pw_name_len - 1] != '\0'
+	      || resultbuf->pw_passwd[pw_resp.pw_passwd_len - 1] != '\0'
+	      || resultbuf->pw_gecos[pw_resp.pw_gecos_len - 1] != '\0'
+	      || resultbuf->pw_dir[pw_resp.pw_dir_len - 1] != '\0'
+	      || resultbuf->pw_shell[pw_resp.pw_shell_len - 1] != '\0')
 	    {
 	      /* We cannot use the database.  */
-	      retval = -1;
+	      retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1;
 	      goto out_close;
 	    }
 
@@ -215,19 +221,21 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type,
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      goto retry;
+      if (retval != -1)
+	goto retry;
     }
 
   return retval;
diff --git a/nscd/nscd_getserv_r.c b/nscd/nscd_getserv_r.c
index ea5dcedb88..a725b1d3de 100644
--- a/nscd/nscd_getserv_r.c
+++ b/nscd/nscd_getserv_r.c
@@ -93,7 +93,6 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
 		     "/", 1), proto ?: "", protolen + 1);
 
  retry:;
-  const serv_response_header *serv_resp = NULL;
   const char *s_name = NULL;
   const char *s_proto = NULL;
   const uint32_t *aliases_len = NULL;
@@ -101,19 +100,32 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
   int retval = -1;
   const char *recend = (const char *) ~UINTMAX_C (0);
   int sock = -1;
+  serv_response_header serv_resp;
+
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (type, key, keylen,
-							  mapped);
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
 
       if (found != NULL)
 	{
-	  serv_resp = &found->data[0].servdata;
-	  s_name = (char *) (serv_resp + 1);
-	  s_proto = s_name + serv_resp->s_name_len;
-	  aliases_len = (uint32_t *) (s_proto + serv_resp->s_proto_len);
+	  s_name = (char *) (&found->data[0].servdata + 1);
+	  serv_resp = found->data[0].servdata;
+	  s_proto = s_name + serv_resp.s_name_len;
+	  aliases_len = (uint32_t *) (s_proto + serv_resp.s_proto_len);
 	  aliases_list = ((char *) aliases_len
-			  + serv_resp->s_aliases_cnt * sizeof (uint32_t));
+			  + serv_resp.s_aliases_cnt * sizeof (uint32_t));
+	  recend = (const char *) found->data + found->recsize;
+	  /* Now check if we can trust serv_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
+	  if (__builtin_expect ((const char *) aliases_len
+				+ serv_resp.s_aliases_cnt * sizeof (uint32_t)
+				> recend, 0))
+	    goto out;
 
 #ifndef _STRING_ARCH_unaligned
 	  /* The aliases_len array in the mapped database might very
@@ -123,46 +135,38 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
 	  if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
 	      != 0)
 	    {
-	      uint32_t *tmp = alloca (hst_resp->h_aliases_cnt
+	      uint32_t *tmp = alloca (serv_resp.s_aliases_cnt
 				      * sizeof (uint32_t));
 	      aliases_len = memcpy (tmp, aliases_len,
-				    hst_resp->h_aliases_cnt
+				    serv_resp.s_aliases_cnt
 				    * sizeof (uint32_t));
 	    }
 #endif
-	  recend = (const char *) found->data + found->recsize;
-	  if (__builtin_expect ((const char *) aliases_len
-				+ serv_resp->s_aliases_cnt * sizeof (uint32_t)
-				> recend, 0))
-	    goto out_close;
 	}
     }
 
-  serv_response_header serv_resp_mem;
-  if (serv_resp == NULL)
+  if (s_name == NULL)
     {
-      sock = __nscd_open_socket (key, keylen, type, &serv_resp_mem,
-				 sizeof (serv_resp_mem));
+      sock = __nscd_open_socket (key, keylen, type, &serv_resp,
+				 sizeof (serv_resp));
       if (sock == -1)
 	{
 	  __nss_not_use_nscd_services = 1;
 	  goto out;
 	}
-
-      serv_resp = &serv_resp_mem;
     }
 
   /* No value found so far.  */
   *result = NULL;
 
-  if (__builtin_expect (serv_resp->found == -1, 0))
+  if (__builtin_expect (serv_resp.found == -1, 0))
     {
       /* The daemon does not cache this database.  */
       __nss_not_use_nscd_services = 1;
       goto out_close;
     }
 
-  if (serv_resp->found == 1)
+  if (serv_resp.found == 1)
     {
       char *cp = buf;
       uintptr_t align1;
@@ -176,13 +180,13 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
 	 align the pointer and the base of the h_addr_list pointers.  */
       align1 = ((__alignof__ (char *) - (cp - ((char *) 0)))
 		& (__alignof__ (char *) - 1));
-      align2 = ((__alignof__ (char *) - ((cp + align1 + serv_resp->s_name_len
-					  + serv_resp->s_proto_len)
+      align2 = ((__alignof__ (char *) - ((cp + align1 + serv_resp.s_name_len
+					  + serv_resp.s_proto_len)
 					 - ((char *) 0)))
 		& (__alignof__ (char *) - 1));
-      if (buflen < (align1 + serv_resp->s_name_len + serv_resp->s_proto_len
+      if (buflen < (align1 + serv_resp.s_name_len + serv_resp.s_proto_len
 		    + align2
-		    + (serv_resp->s_aliases_cnt + 1) * sizeof (char *)))
+		    + (serv_resp.s_aliases_cnt + 1) * sizeof (char *)))
 	{
 	no_room:
 	  __set_errno (ERANGE);
@@ -193,31 +197,31 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
 
       /* Prepare the result as far as we can.  */
       resultbuf->s_aliases = (char **) cp;
-      cp += (serv_resp->s_aliases_cnt + 1) * sizeof (char *);
+      cp += (serv_resp.s_aliases_cnt + 1) * sizeof (char *);
 
       resultbuf->s_name = cp;
-      cp += serv_resp->s_name_len;
+      cp += serv_resp.s_name_len;
       resultbuf->s_proto = cp;
-      cp += serv_resp->s_proto_len + align2;
-      resultbuf->s_port = serv_resp->s_port;
+      cp += serv_resp.s_proto_len + align2;
+      resultbuf->s_port = serv_resp.s_port;
 
       if (s_name == NULL)
 	{
 	  struct iovec vec[2];
 
 	  vec[0].iov_base = resultbuf->s_name;
-	  vec[0].iov_len = serv_resp->s_name_len + serv_resp->s_proto_len;
+	  vec[0].iov_len = serv_resp.s_name_len + serv_resp.s_proto_len;
 	  total_len = vec[0].iov_len;
 	  n = 1;
 
-	  if (serv_resp->s_aliases_cnt > 0)
+	  if (serv_resp.s_aliases_cnt > 0)
 	    {
-	      aliases_len = alloca (serv_resp->s_aliases_cnt
+	      aliases_len = alloca (serv_resp.s_aliases_cnt
 				    * sizeof (uint32_t));
 	      vec[n].iov_base = (void *) aliases_len;
-	      vec[n].iov_len = serv_resp->s_aliases_cnt * sizeof (uint32_t);
+	      vec[n].iov_len = serv_resp.s_aliases_cnt * sizeof (uint32_t);
 
-	      total_len += serv_resp->s_aliases_cnt * sizeof (uint32_t);
+	      total_len += serv_resp.s_aliases_cnt * sizeof (uint32_t);
 	      ++n;
 	    }
 
@@ -226,11 +230,11 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
 	}
       else
 	memcpy (resultbuf->s_name, s_name,
-		serv_resp->s_name_len + serv_resp->s_proto_len);
+		serv_resp.s_name_len + serv_resp.s_proto_len);
 
       /*  Now we also can read the aliases.  */
       total_len = 0;
-      for (cnt = 0; cnt < serv_resp->s_aliases_cnt; ++cnt)
+      for (cnt = 0; cnt < serv_resp.s_aliases_cnt; ++cnt)
 	{
 	  resultbuf->s_aliases[cnt] = cp;
 	  cp += aliases_len[cnt];
@@ -240,10 +244,26 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
 
       if (__builtin_expect ((const char *) aliases_list + total_len > recend,
 			    0))
-	goto out_close;
+	{
+	  /* aliases_len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (aliases_list != NULL && mapped->head->gc_cycle != gc_cycle)
+	    retval = -2;
+	  goto out_close;
+	}
+
       /* See whether this would exceed the buffer capacity.  */
       if (__builtin_expect (cp > buf + buflen, 0))
-	goto no_room;
+	{
+	  /* aliases_len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (aliases_list != NULL && mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out_close;
+	    }
+	  goto no_room;
+	}
 
       /* And finally read the aliases.  */
       if (aliases_list == NULL)
@@ -261,15 +281,19 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
 	  memcpy (resultbuf->s_aliases[0], aliases_list, total_len);
 
 	  /* Try to detect corrupt databases.  */
-	  if (resultbuf->s_name[serv_resp->s_name_len - 1] != '\0'
-	      || resultbuf->s_proto[serv_resp->s_proto_len - 1] != '\0'
-	      || ({for (cnt = 0; cnt < serv_resp->s_aliases_cnt; ++cnt)
+	  if (resultbuf->s_name[serv_resp.s_name_len - 1] != '\0'
+	      || resultbuf->s_proto[serv_resp.s_proto_len - 1] != '\0'
+	      || ({for (cnt = 0; cnt < serv_resp.s_aliases_cnt; ++cnt)
 		     if (resultbuf->s_aliases[cnt][aliases_len[cnt] - 1]
 			 != '\0')
 		       break;
-		   cnt < serv_resp->s_aliases_cnt; }))
-	    /* We cannot use the database.  */
-	    goto out_close;
+		   cnt < serv_resp.s_aliases_cnt; }))
+	    {
+	      /* We cannot use the database.  */
+	      if (mapped->head->gc_cycle != gc_cycle)
+		retval = -2;
+	      goto out_close;
+	    }
 
 	  retval = 0;
 	  *result = resultbuf;
@@ -287,19 +311,21 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0 || ++nretries == 5)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      goto retry;
+      if (retval != -1)
+	goto retry;
     }
 
   return retval;
diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c
index 7c45981586..394b2f86e6 100644
--- a/nscd/nscd_helper.c
+++ b/nscd/nscd_helper.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2002,2003,2004,2005,2006,2007
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -21,6 +22,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
+#include <string.h>
 #include <time.h>
 #include <unistd.h>
 #include <sys/mman.h>
@@ -95,16 +97,20 @@ __readvall (int fd, const struct iovec *iov, int iovcnt)
 
 
 static int
-open_socket (void)
+open_socket (request_type type, const char *key, size_t keylen)
 {
   int sock = __socket (PF_UNIX, SOCK_STREAM, 0);
   if (sock < 0)
     return -1;
 
+  struct
+  {
+    request_header req;
+    char key[keylen];
+  } reqdata;
+
   /* Make socket non-blocking.  */
-  int fl = __fcntl (sock, F_GETFL);
-  if (fl != -1)
-    __fcntl (sock, F_SETFL, fl | O_NONBLOCK);
+  __fcntl (sock, F_SETFL, O_RDWR | O_NONBLOCK);
 
   struct sockaddr_un sun;
   sun.sun_family = AF_UNIX;
@@ -113,13 +119,56 @@ open_socket (void)
       && errno != EINPROGRESS)
     goto out;
 
-  struct pollfd fds[1];
-  fds[0].fd = sock;
-  fds[0].events = POLLOUT | POLLERR | POLLHUP;
-  if (__poll (fds, 1, 5 * 1000) > 0)
-    /* Success.  We do not check for success of the connect call here.
-       If it failed, the following operations will fail.  */
-    return sock;
+  reqdata.req.version = NSCD_VERSION;
+  reqdata.req.type = type;
+  reqdata.req.key_len = keylen;
+
+  memcpy (reqdata.key, key, keylen);
+
+  bool first_try = true;
+  struct timeval tvend;
+  while (1)
+    {
+#ifndef MSG_NOSIGNAL
+# define MSG_NOSIGNAL 0
+#endif
+      ssize_t wres = TEMP_FAILURE_RETRY (__send (sock, &reqdata,
+						 sizeof (reqdata),
+						 MSG_NOSIGNAL));
+      if (__builtin_expect (wres == (ssize_t) sizeof (reqdata), 1))
+	/* We managed to send the request.  */
+	return sock;
+
+      if (wres != -1 || errno != EAGAIN)
+	/* Something is really wrong, no chance to continue.  */
+	break;
+
+      /* The daemon is busy wait for it.  */
+      int to;
+      if (first_try)
+	{
+	  gettimeofday (&tvend, NULL);
+	  tvend.tv_sec += 5;
+	  to = 5 * 1000;
+	  first_try = false;
+	}
+      else
+	{
+	  struct timeval now;
+	  gettimeofday (&now, NULL);
+	  to = ((tvend.tv_sec - now.tv_sec) * 1000
+		+ (tvend.tv_usec - now.tv_usec) / 1000);
+	}
+
+      struct pollfd fds[1];
+      fds[0].fd = sock;
+      fds[0].events = POLLOUT | POLLERR | POLLHUP;
+      if (__poll (fds, 1, to) <= 0)
+	/* The connection timed out or broke down.  */
+	break;
+
+      /* We try to write again.  */
+    }
 
  out:
   close_not_cancel_no_status (sock);
@@ -179,36 +228,15 @@ get_mapping (request_type type, const char *key,
   int saved_errno = errno;
 
   int mapfd = -1;
+  char resdata[keylen];
 
-  /* Send the request.  */
-  struct
-  {
-    request_header req;
-    char key[keylen];
-  } reqdata;
-
-  int sock = open_socket ();
+  /* Open a socket and send the request.  */
+  int sock = open_socket (type, key, keylen);
   if (sock < 0)
     goto out;
 
-  reqdata.req.version = NSCD_VERSION;
-  reqdata.req.type = type;
-  reqdata.req.key_len = keylen;
-  memcpy (reqdata.key, key, keylen);
-
-# ifndef MSG_NOSIGNAL
-#  define MSG_NOSIGNAL 0
-# endif
-  if (__builtin_expect (TEMP_FAILURE_RETRY (__send (sock, &reqdata,
-						    sizeof (reqdata),
-						    MSG_NOSIGNAL))
-			!= sizeof (reqdata), 0))
-    /* We cannot even write the request.  */
-    goto out_close2;
-
   /* Room for the data sent along with the file descriptor.  We expect
      the key name back.  */
-# define resdata reqdata.key
   struct iovec iov[1];
   iov[0].iov_base = resdata;
   iov[0].iov_len = keylen;
@@ -362,7 +390,10 @@ __nscd_get_map_ref (request_type type, const char *name,
 }
 
 
-const struct datahead *
+/* Don't return const struct datahead *, as eventhough the record
+   is normally constant, it can change arbitrarily during nscd
+   garbage collection.  */
+struct datahead *
 __nscd_cache_search (request_type type, const char *key, size_t keylen,
 		     const struct mapped_database *mapped)
 {
@@ -374,16 +405,32 @@ __nscd_cache_search (request_type type, const char *key, size_t keylen,
     {
       struct hashentry *here = (struct hashentry *) (mapped->data + work);
 
+#ifndef _STRING_ARCH_unaligned
+      /* Although during garbage collection when moving struct hashentry
+	 records around we first copy from old to new location and then
+	 adjust pointer from previous hashentry to it, there is no barrier
+	 between those memory writes.  It is very unlikely to hit it,
+	 so check alignment only if a misaligned load can crash the
+	 application.  */
+      if ((uintptr_t) here & (__alignof__ (*here) - 1))
+	return NULL;
+#endif
+
       if (type == here->type
 	  && keylen == here->len
-	  && here->key + here->len <= datasize
+	  && here->key + keylen <= datasize
 	  && memcmp (key, mapped->data + here->key, keylen) == 0
 	  && here->packet + sizeof (struct datahead) <= datasize)
 	{
 	  /* We found the entry.  Increment the appropriate counter.  */
-	  const struct datahead *dh
+	  struct datahead *dh
 	    = (struct datahead *) (mapped->data + here->packet);
 
+#ifndef _STRING_ARCH_unaligned
+	  if ((uintptr_t) dh & (__alignof__ (*dh) - 1))
+	    return NULL;
+#endif
+
 	  /* See whether we must ignore the entry or whether something
 	     is wrong because garbage collection is in progress.  */
 	  if (dh->usable && here->packet + dh->allocsize <= datasize)
@@ -402,28 +449,22 @@ int
 __nscd_open_socket (const char *key, size_t keylen, request_type type,
 		    void *response, size_t responselen)
 {
+  /* This should never happen and it is something the nscd daemon
+     enforces, too.  He it helps to limit the amount of stack
+     used.  */
+  if (keylen > MAXKEYLEN)
+    return -1;
+
   int saved_errno = errno;
 
-  int sock = open_socket ();
+  int sock = open_socket (type, key, keylen);
   if (sock >= 0)
     {
-      request_header req;
-      req.version = NSCD_VERSION;
-      req.type = type;
-      req.key_len = keylen;
-
-      struct iovec vec[2];
-      vec[0].iov_base = &req;
-      vec[0].iov_len = sizeof (request_header);
-      vec[1].iov_base = (void *) key;
-      vec[1].iov_len = keylen;
-
-      ssize_t nbytes = TEMP_FAILURE_RETRY (__writev (sock, vec, 2));
-      if (nbytes == (ssize_t) (sizeof (request_header) + keylen)
-	  /* Wait for data.  */
-	  && wait_on_socket (sock) > 0)
+      /* Wait for data.  */
+      if (wait_on_socket (sock) > 0)
 	{
-	  nbytes = TEMP_FAILURE_RETRY (__read (sock, response, responselen));
+	  ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, response,
+						       responselen));
 	  if (nbytes == (ssize_t) responselen)
 	    return sock;
 	}
diff --git a/nscd/nscd_initgroups.c b/nscd/nscd_initgroups.c
index 97a037d4a9..866455a96c 100644
--- a/nscd/nscd_initgroups.c
+++ b/nscd/nscd_initgroups.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -39,6 +39,7 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
 {
   size_t userlen = strlen (user) + 1;
   int gc_cycle;
+  int nretries = 0;
 
   /* If the mapping is available, try to search there instead of
      communicating with the nscd.  */
@@ -46,44 +47,49 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
   mapped = __nscd_get_map_ref (GETFDGR, "group", &__gr_map_handle, &gc_cycle);
 
  retry:;
-  const initgr_response_header *initgr_resp = NULL;
   char *respdata = NULL;
   int retval = -1;
   int sock = -1;
+  initgr_response_header initgr_resp;
 
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (INITGROUPS, user,
-							  userlen, mapped);
+      struct datahead *found = __nscd_cache_search (INITGROUPS, user,
+						    userlen, mapped);
       if (found != NULL)
 	{
-	  initgr_resp = &found->data[0].initgrdata;
-	  respdata = (char *) (initgr_resp + 1);
+	  respdata = (char *) (&found->data[0].initgrdata + 1);
+	  initgr_resp = found->data[0].initgrdata;
 	  char *recend = (char *) found->data + found->recsize;
 
-	  if (respdata + initgr_resp->ngrps * sizeof (int32_t) > recend)
+	  /* Now check if we can trust initgr_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
+
+	  if (respdata + initgr_resp.ngrps * sizeof (int32_t) > recend)
 	    goto out;
 	}
     }
 
   /* If we do not have the cache mapped, try to get the data over the
      socket.  */
-  initgr_response_header initgr_resp_mem;
-  if (initgr_resp == NULL)
+  if (respdata == NULL)
     {
-      sock = __nscd_open_socket (user, userlen, INITGROUPS, &initgr_resp_mem,
-				 sizeof (initgr_resp_mem));
+      sock = __nscd_open_socket (user, userlen, INITGROUPS, &initgr_resp,
+				 sizeof (initgr_resp));
       if (sock == -1)
 	{
 	  /* nscd not running or wrong version.  */
 	  __nss_not_use_nscd_group = 1;
 	  goto out;
 	}
-
-      initgr_resp = &initgr_resp_mem;
     }
 
-  if (initgr_resp->found == 1)
+  if (initgr_resp.found == 1)
     {
       /* The following code assumes that gid_t and int32_t are the
 	 same size.  This is the case for al existing implementation.
@@ -91,40 +97,40 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
 	 doesn't use memcpy but instead copies each array element one
 	 by one.  */
       assert (sizeof (int32_t) == sizeof (gid_t));
-      assert (initgr_resp->ngrps >= 0);
+      assert (initgr_resp.ngrps >= 0);
 
       /* Make sure we have enough room.  We always count GROUP in even
 	 though we might not end up adding it.  */
-      if (*size < initgr_resp->ngrps + 1)
+      if (*size < initgr_resp.ngrps + 1)
 	{
 	  gid_t *newp = realloc (*groupsp,
-				 (initgr_resp->ngrps + 1) * sizeof (gid_t));
+				 (initgr_resp.ngrps + 1) * sizeof (gid_t));
 	  if (newp == NULL)
 	    /* We cannot increase the buffer size.  */
 	    goto out_close;
 
 	  *groupsp = newp;
-	  *size = initgr_resp->ngrps + 1;
+	  *size = initgr_resp.ngrps + 1;
 	}
 
       if (respdata == NULL)
 	{
 	  /* Read the data from the socket.  */
-	  if ((size_t) __readall (sock, *groupsp, initgr_resp->ngrps
+	  if ((size_t) __readall (sock, *groupsp, initgr_resp.ngrps
 						  * sizeof (gid_t))
-	      == initgr_resp->ngrps * sizeof (gid_t))
-	    retval = initgr_resp->ngrps;
+	      == initgr_resp.ngrps * sizeof (gid_t))
+	    retval = initgr_resp.ngrps;
 	}
       else
 	{
 	  /* Just copy the data.  */
-	  retval = initgr_resp->ngrps;
+	  retval = initgr_resp.ngrps;
 	  memcpy (*groupsp, respdata, retval * sizeof (gid_t));
 	}
     }
   else
     {
-      if (__builtin_expect (initgr_resp->found == -1, 0))
+      if (__builtin_expect (initgr_resp.found == -1, 0))
 	{
 	  /* The daemon does not cache this database.  */
 	  __nss_not_use_nscd_group = 1;
@@ -153,19 +159,21 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      goto retry;
+      if (retval != -1)
+	goto retry;
     }
 
   return retval;
diff --git a/scripts/gen-as-const.awk b/scripts/gen-as-const.awk
index c529fa42c8..bc3c47fb73 100644
--- a/scripts/gen-as-const.awk
+++ b/scripts/gen-as-const.awk
@@ -38,7 +38,7 @@ NF > 1 {
   if (test)
     print "  TEST (" name ", \"" FILENAME ":" FNR "\", " $0 ")";
   else
-    printf "asm (\"@@@name@@@%s@@@value@@@%%0@@@end@@@\" : : \"i\" (%s));\n",
+    printf "asm (\"@@@name@@@%s@@@value@@@%%0@@@end@@@\" : : \"i\" ((long) %s));\n",
       name, $0;
 }
 
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 37bcdb3bc8..98220550f4 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
+# Copyright (C) 1991-2006, 2007 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
@@ -54,7 +54,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
 	 tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \
 	 tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 bug15 \
 	 tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \
-	 tst-fwrite bug16
+	 tst-fwrite bug16 bug17
 
 test-srcs = tst-unbputc tst-printf
 
diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c
index f61b23fceb..373843f1cd 100644
--- a/stdio-common/_itoa.c
+++ b/stdio-common/_itoa.c
@@ -1,5 +1,5 @@
 /* Internal function for converting integers to ASCII.
-   Copyright (C) 1994, 1995, 1996, 1999, 2000, 2002, 2003, 2004
+   Copyright (C) 1994, 1995, 1996, 1999, 2000, 2002, 2003, 2004, 2007
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Torbjorn Granlund <tege@matematik.su.se>
@@ -22,6 +22,7 @@
 
 #include <gmp-mparam.h>
 #include <gmp.h>
+#include <limits.h>
 #include <stdlib/gmp-impl.h>
 #include <stdlib/longlong.h>
 
@@ -78,10 +79,12 @@ struct base_table_t
 #endif
 
 
+/* We do not compile _itoa if we always can use _itoa_word.  */
+#if LLONG_MAX != LONG_MAX
 /* Local variables.  */
 const struct base_table_t _itoa_base_table[] attribute_hidden =
 {
-#if BITS_PER_MP_LIMB == 64
+# if BITS_PER_MP_LIMB == 64
   /*  2 */ {SEL1(0ull) 1, 1},
   /*  3 */ {SEL1(0xaaaaaaaaaaaaaaabull) 0, 1},
   /*  4 */ {SEL1(0ull) 1, 2},
@@ -117,8 +120,8 @@ const struct base_table_t _itoa_base_table[] attribute_hidden =
   /* 34 */ {SEL1(0xf0f0f0f0f0f0f0f1ull) 0, 5},
   /* 35 */ {SEL1(0xea0ea0ea0ea0ea0full) 0, 5},
   /* 36 */ {SEL1(0xe38e38e38e38e38full) 0, 5}
-#endif
-#if BITS_PER_MP_LIMB == 32
+# endif
+# if BITS_PER_MP_LIMB == 32
   /*  2 */ {SEL1(0ul) 1, 1, {0, 31, 0x80000000ul SEL2(0xfffffffful)}},
   /*  3 */ {SEL1(0xaaaaaaabul) 0, 1, {0, 20, 0xcfd41b91ul SEL2(0x3b563c24ul)}},
   /*  4 */ {SEL1(0ul) 1, 2, {1, 15, 0x40000000ul SEL2(0xfffffffful)}},
@@ -154,8 +157,9 @@ const struct base_table_t _itoa_base_table[] attribute_hidden =
   /* 34 */ {SEL1(0xf0f0f0f1ul) 0, 5, {1, 6, 0x5c13d840ul SEL2(0x63dfc229ul)}},
   /* 35 */ {SEL1(0xd41d41d5ul) 1, 6, {1, 6, 0x6d91b519ul SEL2(0x2b0fee30ul)}},
   /* 36 */ {SEL1(0x38e38e39ul) 0, 3, {0, 6, 0x81bf1000ul SEL2(0xf91bd1b6ul)}}
-#endif
+# endif
 };
+#endif
 
 /* Lower-case digits.  */
 extern const char _itoa_lower_digits[];
@@ -201,6 +205,7 @@ _itoa_word (unsigned long value, char *buflim,
 #undef SPECIAL
 
 
+#if LLONG_MAX != LONG_MAX
 char *
 _itoa (value, buflim, base, upper_case)
      unsigned long long int value;
@@ -215,7 +220,7 @@ _itoa (value, buflim, base, upper_case)
 
   switch (base)
     {
-#define RUN_2N(BITS) \
+# define RUN_2N(BITS) \
       do								      \
         {								      \
 	  /* `unsigned long long int' always has 64 bits.  */		      \
@@ -269,7 +274,8 @@ _itoa (value, buflim, base, upper_case)
 
     default:
       {
-#if BITS_PER_MP_LIMB == 64
+	char *bufend = buflim;
+# if BITS_PER_MP_LIMB == 64
 	mp_limb_t base_multiplier = brec->base_multiplier;
 	if (brec->flag)
 	  while (value != 0)
@@ -293,8 +299,8 @@ _itoa (value, buflim, base, upper_case)
 	      *--buflim = digits[rem];
 	      value = quo;
 	    }
-#endif
-#if BITS_PER_MP_LIMB == 32
+# endif
+# if BITS_PER_MP_LIMB == 32
 	mp_limb_t t[3];
 	int n;
 
@@ -302,11 +308,11 @@ _itoa (value, buflim, base, upper_case)
 	   Optimize for frequent cases of 32 bit numbers.  */
 	if ((mp_limb_t) (value >> 32) >= 1)
 	  {
-#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION
+#  if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION
 	    int big_normalization_steps = brec->big.normalization_steps;
 	    mp_limb_t big_base_norm
 	      = brec->big.base << big_normalization_steps;
-#endif
+#  endif
 	    if ((mp_limb_t) (value >> 32) >= brec->big.base)
 	      {
 		mp_limb_t x1hi, x1lo, r;
@@ -315,7 +321,7 @@ _itoa (value, buflim, base, upper_case)
 		   always be very small.  It might be faster just to
 		   subtract in a tight loop.  */
 
-#if UDIV_TIME > 2 * UMUL_TIME
+#  if UDIV_TIME > 2 * UMUL_TIME
 		mp_limb_t x, xh, xl;
 
 		if (big_normalization_steps == 0)
@@ -340,7 +346,7 @@ _itoa (value, buflim, base, upper_case)
 		udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm,
 				   brec->big.base_ninv);
 		t[1] = x >> big_normalization_steps;
-#elif UDIV_NEEDS_NORMALIZATION
+#  elif UDIV_NEEDS_NORMALIZATION
 		mp_limb_t x, xh, xl;
 
 		if (big_normalization_steps == 0)
@@ -362,17 +368,17 @@ _itoa (value, buflim, base, upper_case)
 		xl = x1lo << big_normalization_steps;
 		udiv_qrnnd (t[0], x, xh, xl, big_base_norm);
 		t[1] = x >> big_normalization_steps;
-#else
+#  else
 		udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32),
 			    brec->big.base);
 		udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base);
 		udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base);
-#endif
+#  endif
 		n = 3;
 	      }
 	    else
 	      {
-#if (UDIV_TIME > 2 * UMUL_TIME)
+#  if UDIV_TIME > 2 * UMUL_TIME
 		mp_limb_t x;
 
 		value <<= brec->big.normalization_steps;
@@ -380,17 +386,17 @@ _itoa (value, buflim, base, upper_case)
 				   (mp_limb_t) value, big_base_norm,
 				   brec->big.base_ninv);
 		t[1] = x >> brec->big.normalization_steps;
-#elif UDIV_NEEDS_NORMALIZATION
+#  elif UDIV_NEEDS_NORMALIZATION
 		mp_limb_t x;
 
 		value <<= big_normalization_steps;
 		udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32),
 			    (mp_limb_t) value, big_base_norm);
 		t[1] = x >> big_normalization_steps;
-#else
+#  else
 		udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32),
 			    (mp_limb_t) value, brec->big.base);
-#endif
+#  endif
 		n = 2;
 	      }
 	  }
@@ -406,7 +412,7 @@ _itoa (value, buflim, base, upper_case)
 	    mp_limb_t ti = t[--n];
 	    int ndig_for_this_limb = 0;
 
-#if UDIV_TIME > 2 * UMUL_TIME
+#  if UDIV_TIME > 2 * UMUL_TIME
 	    mp_limb_t base_multiplier = brec->base_multiplier;
 	    if (brec->flag)
 	      while (ti != 0)
@@ -432,7 +438,7 @@ _itoa (value, buflim, base, upper_case)
 		  ti = quo;
 		  ++ndig_for_this_limb;
 		}
-#else
+#  else
 	    while (ti != 0)
 	      {
 		mp_limb_t quo, rem;
@@ -443,7 +449,7 @@ _itoa (value, buflim, base, upper_case)
 		ti = quo;
 		++ndig_for_this_limb;
 	      }
-#endif
+#  endif
 	    /* If this wasn't the most significant word, pad with zeros.  */
 	    if (n != 0)
 	      while (ndig_for_this_limb < brec->big.ndigits)
@@ -453,13 +459,16 @@ _itoa (value, buflim, base, upper_case)
 		}
 	  }
 	while (n != 0);
-#endif
+# endif
+	if (buflim == bufend)
+	  *--buflim = '0';
       }
       break;
     }
 
   return buflim;
 }
+#endif
 
 char *
 _fitoa_word (unsigned long value, char *buf, unsigned int base, int upper_case)
@@ -471,6 +480,7 @@ _fitoa_word (unsigned long value, char *buf, unsigned int base, int upper_case)
   return buf;
 }
 
+#if LLONG_MAX != LONG_MAX
 char *
 _fitoa (unsigned long long value, char *buf, unsigned int base, int upper_case)
 {
@@ -480,3 +490,4 @@ _fitoa (unsigned long long value, char *buf, unsigned int base, int upper_case)
     *buf++ = *cp++;
   return buf;
 }
+#endif
diff --git a/stdio-common/_itoa.h b/stdio-common/_itoa.h
index 21a9c39294..6d9812fe32 100644
--- a/stdio-common/_itoa.h
+++ b/stdio-common/_itoa.h
@@ -1,5 +1,5 @@
 /* Internal function for converting integers to ASCII.
-   Copyright (C) 1994,95,96,97,98,99,2002,2003 Free Software Foundation, Inc.
+   Copyright (C) 1994-1999,2002,2003,2007 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
@@ -19,7 +19,8 @@
 
 #ifndef _ITOA_H
 #define _ITOA_H
-#include <sys/cdefs.h>
+
+#include <limits.h>
 
 /* Convert VALUE into ASCII in base BASE (2..36).
    Write backwards starting the character just before BUFLIM.
@@ -81,4 +82,12 @@ extern char *_fitoa_word (unsigned long value, char *buf, unsigned int base,
 extern char *_fitoa (unsigned long long value, char *buf, unsigned int base,
 		     int upper_case) attribute_hidden;
 
+#if LONG_MAX == LLONG_MAX
+/* No need for special long long versions.  */
+# define _itoa(value, buf, base, upper_case) \
+  _itoa_word (value, buf, base, upper_case)
+# define _fitoa(value, buf, base, upper_case) \
+  _fitoa_word (value, buf, base, upper_case)
+#endif
+
 #endif	/* itoa.h */
diff --git a/stdio-common/_itowa.c b/stdio-common/_itowa.c
index b9cc341dd9..09a961dfaf 100644
--- a/stdio-common/_itowa.c
+++ b/stdio-common/_itowa.c
@@ -1,5 +1,5 @@
 /* Internal function for converting integers to ASCII.
-   Copyright (C) 1994,1995,1996,1999,2000,2002 Free Software Foundation, Inc.
+   Copyright (C) 1994-1996,1999,2000,2002,2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Torbjorn Granlund <tege@matematik.su.se>
    and Ulrich Drepper <drepper@gnu.org>.
@@ -21,6 +21,7 @@
 
 #include <gmp-mparam.h>
 #include <gmp.h>
+#include <limits.h>
 #include <stdlib/gmp-impl.h>
 #include <stdlib/longlong.h>
 
@@ -85,6 +86,7 @@ extern const wchar_t _itowa_lower_digits[] attribute_hidden;
 extern const wchar_t _itowa_upper_digits[] attribute_hidden;
 
 
+#if LLONG_MAX != LONG_MAX
 wchar_t *
 _itowa (value, buflim, base, upper_case)
      unsigned long long int value;
@@ -99,7 +101,7 @@ _itowa (value, buflim, base, upper_case)
 
   switch (base)
     {
-#define RUN_2N(BITS) \
+# define RUN_2N(BITS) \
       do								      \
         {								      \
 	  /* `unsigned long long int' always has 64 bits.  */		      \
@@ -153,7 +155,7 @@ _itowa (value, buflim, base, upper_case)
 
     default:
       {
-#if BITS_PER_MP_LIMB == 64
+# if BITS_PER_MP_LIMB == 64
 	mp_limb_t base_multiplier = brec->base_multiplier;
 	if (brec->flag)
 	  while (value != 0)
@@ -177,8 +179,8 @@ _itowa (value, buflim, base, upper_case)
 	      *--bp = digits[rem];
 	      value = quo;
 	    }
-#endif
-#if BITS_PER_MP_LIMB == 32
+# endif
+# if BITS_PER_MP_LIMB == 32
 	mp_limb_t t[3];
 	int n;
 
@@ -186,11 +188,11 @@ _itowa (value, buflim, base, upper_case)
 	   Optimize for frequent cases of 32 bit numbers.  */
 	if ((mp_limb_t) (value >> 32) >= 1)
 	  {
-#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION
+# if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION
 	    int big_normalization_steps = brec->big.normalization_steps;
 	    mp_limb_t big_base_norm
 	      = brec->big.base << big_normalization_steps;
-#endif
+# endif
 	    if ((mp_limb_t) (value >> 32) >= brec->big.base)
 	      {
 		mp_limb_t x1hi, x1lo, r;
@@ -199,7 +201,7 @@ _itowa (value, buflim, base, upper_case)
 		   always be very small.  It might be faster just to
 		   subtract in a tight loop.  */
 
-#if UDIV_TIME > 2 * UMUL_TIME
+# if UDIV_TIME > 2 * UMUL_TIME
 		mp_limb_t x, xh, xl;
 
 		if (big_normalization_steps == 0)
@@ -224,7 +226,7 @@ _itowa (value, buflim, base, upper_case)
 		udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm,
 				   brec->big.base_ninv);
 		t[1] = x >> big_normalization_steps;
-#elif UDIV_NEEDS_NORMALIZATION
+# elif UDIV_NEEDS_NORMALIZATION
 		mp_limb_t x, xh, xl;
 
 		if (big_normalization_steps == 0)
@@ -246,17 +248,17 @@ _itowa (value, buflim, base, upper_case)
 		xl = x1lo << big_normalization_steps;
 		udiv_qrnnd (t[0], x, xh, xl, big_base_norm);
 		t[1] = x >> big_normalization_steps;
-#else
+# else
 		udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32),
 			    brec->big.base);
 		udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base);
 		udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base);
-#endif
+# endif
 		n = 3;
 	      }
 	    else
 	      {
-#if (UDIV_TIME > 2 * UMUL_TIME)
+# if UDIV_TIME > 2 * UMUL_TIME
 		mp_limb_t x;
 
 		value <<= brec->big.normalization_steps;
@@ -264,17 +266,17 @@ _itowa (value, buflim, base, upper_case)
 				   (mp_limb_t) value, big_base_norm,
 				   brec->big.base_ninv);
 		t[1] = x >> brec->big.normalization_steps;
-#elif UDIV_NEEDS_NORMALIZATION
+# elif UDIV_NEEDS_NORMALIZATION
 		mp_limb_t x;
 
 		value <<= big_normalization_steps;
 		udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32),
 			    (mp_limb_t) value, big_base_norm);
 		t[1] = x >> big_normalization_steps;
-#else
+# else
 		udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32),
 			    (mp_limb_t) value, brec->big.base);
-#endif
+# endif
 		n = 2;
 	      }
 	  }
@@ -290,7 +292,7 @@ _itowa (value, buflim, base, upper_case)
 	    mp_limb_t ti = t[--n];
 	    int ndig_for_this_limb = 0;
 
-#if UDIV_TIME > 2 * UMUL_TIME
+# if UDIV_TIME > 2 * UMUL_TIME
 	    mp_limb_t base_multiplier = brec->base_multiplier;
 	    if (brec->flag)
 	      while (ti != 0)
@@ -316,7 +318,7 @@ _itowa (value, buflim, base, upper_case)
 		  ti = quo;
 		  ++ndig_for_this_limb;
 		}
-#else
+# else
 	    while (ti != 0)
 	      {
 		mp_limb_t quo, rem;
@@ -327,7 +329,7 @@ _itowa (value, buflim, base, upper_case)
 		ti = quo;
 		++ndig_for_this_limb;
 	      }
-#endif
+# endif
 	    /* If this wasn't the most significant word, pad with zeros.  */
 	    if (n != 0)
 	      while (ndig_for_this_limb < brec->big.ndigits)
@@ -337,10 +339,11 @@ _itowa (value, buflim, base, upper_case)
 		}
 	  }
 	while (n != 0);
-#endif
+# endif
       }
       break;
     }
 
   return bp;
 }
+#endif
diff --git a/stdio-common/bug17.c b/stdio-common/bug17.c
new file mode 100644
index 0000000000..2ef398674b
--- /dev/null
+++ b/stdio-common/bug17.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <string.h>
+
+static int
+do_test (void)
+{
+  static const char expect[] = "0, 0, 0";
+  char buf[100];
+  int status = 0;
+
+  static const char fmt1[] = "%0d, %0ld, %0lld";
+  snprintf (buf, sizeof (buf), fmt1, 0, 0L, 0LL);
+  if (strcmp (buf, expect) != 0)
+    {
+      printf ("\"%s\": got \"%s\", expected \"%s\"\n", fmt1, buf, expect);
+      status = 1;
+    }
+
+  static const char fmt2[] = "%0u, %0lu, %0llu";
+  snprintf (buf, sizeof (buf), fmt2, 0u, 0uL, 0uLL);
+  if (strcmp (buf, expect) != 0)
+    {
+      printf ("\"%s\": got \"%s\", expected \"%s\"\n", fmt2, buf, expect);
+      status = 1;
+    }
+
+  return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/string/Makefile b/string/Makefile
index f087022b3c..d4ec22457d 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -40,7 +40,7 @@ routines	:= strcat strchr strcmp strcoll strcpy strcspn		\
 				     addsep replace)			\
 		   envz basename					\
 		   strcoll_l strxfrm_l string-inlines memrchr		\
-		   xpg-strerror
+		   xpg-strerror strerror_l
 
 # Gcc internally generates calls to unbounded memcpy and memset
 # for -fbounded-pointer compiles.  Glibc uses memchr for explicit checks.
diff --git a/string/Versions b/string/Versions
index ee5dee903f..f145fd34a4 100644
--- a/string/Versions
+++ b/string/Versions
@@ -77,4 +77,7 @@ libc {
     # x*
     __xpg_strerror_r;
   }
+  GLIBC_2.6 {
+    strerror_l;
+  }
 }
diff --git a/string/strerror_l.c b/string/strerror_l.c
new file mode 100644
index 0000000000..348a3c50ec
--- /dev/null
+++ b/string/strerror_l.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2007 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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+
+
+static __thread char *last_value;
+
+
+static const char *
+translate (const char *str, locale_t loc)
+{
+  locale_t oldloc = __uselocale (loc);
+  const char *res = _(str);
+  __uselocale (oldloc);
+  return res;
+}
+
+
+/* Return a string describing the errno code in ERRNUM.  */
+char *
+strerror_l (int errnum, locale_t loc)
+{
+
+
+  if (__builtin_expect (errnum < 0 || errnum >= _sys_nerr_internal
+			|| _sys_errlist_internal[errnum] == NULL, 0))
+    {
+      free (last_value);
+      if (__asprintf (&last_value, "%s%d",
+		      translate ("Unknown error ", loc), errnum) == -1)
+	last_value = NULL;
+
+      return last_value;
+    }
+
+  return (char *) translate (_sys_errlist_internal[errnum], loc);
+}
+
+
+#ifdef _LIBC
+# ifdef _LIBC_REENTRANT
+/* This is called when a thread is exiting to free the last_value string.  */
+static void __attribute__ ((section ("__libc_thread_freeres_fn")))
+strerror_thread_freeres (void)
+{
+  free (last_value);
+}
+text_set_element (__libc_thread_subfreeres, strerror_thread_freeres);
+text_set_element (__libc_subfreeres, strerror_thread_freeres);
+# endif
+#endif
diff --git a/string/string.h b/string/string.h
index 1adf925bb0..5e1a96fc06 100644
--- a/string/string.h
+++ b/string/string.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-1993, 1995-2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1991-1993, 1995-2004, 2007 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
@@ -283,6 +283,12 @@ extern char *strerror_r (int __errnum, char *__buf, size_t __buflen)
 # endif
 #endif
 
+#ifdef __USE_GNU
+/* Translate error number to string according to the locale L.  */
+extern char *strerror_l (int __errnum, __locale_t __l) __THROW;
+#endif
+
+
 /* We define this function always since `bzero' is sometimes needed when
    the namespace rules does not allow this.  */
 extern void __bzero (void *__s, size_t __n) __THROW __nonnull ((1));
diff --git a/sysdeps/i386/bits/byteswap.h b/sysdeps/i386/bits/byteswap.h
index bed27559c5..3baad85e8a 100644
--- a/sysdeps/i386/bits/byteswap.h
+++ b/sysdeps/i386/bits/byteswap.h
@@ -1,5 +1,6 @@
 /* Macros to swap the order of bytes in integer values.
-   Copyright (C) 1997,1998,2000,2002,2003,2006 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2000, 2002, 2003, 2006, 2007
+   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
@@ -66,7 +67,8 @@ __bswap_16 (unsigned short int __bsx)
    `bswap' opcode.  On i386 we have to use three instructions.  */
 #  if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \
       && !defined __pentium4__ && !defined __k8__ && !defined __athlon__ \
-      && !defined __k6__
+      && !defined __k6__ && !defined __nocona__ && !defined __core2__ \
+      && !defined __geode__
 #   define __bswap_32(x)						      \
      (__extension__							      \
       ({ register unsigned int __v, __x = (x);				      \
diff --git a/sysdeps/i386/dl-trampoline.S b/sysdeps/i386/dl-trampoline.S
index fd87eb711d..f991797ee9 100644
--- a/sysdeps/i386/dl-trampoline.S
+++ b/sysdeps/i386/dl-trampoline.S
@@ -1,5 +1,5 @@
 /* PLT trampolines.  i386 version.
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2007 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
@@ -101,29 +101,29 @@ _dl_runtime_profile:
 	*/
 	cfi_adjust_cfa_offset (12)
 1:	movl %ebx, (%esp)
-	cfi_rel_offset (3, 0)
+	cfi_rel_offset (ebx, 0)
 	movl %edx, %ebx		# This is the frame buffer size
 	pushl %edi
 	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (7, 0)
+	cfi_rel_offset (edi, 0)
 	pushl %esi
 	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (6, 0)
+	cfi_rel_offset (esi, 0)
 	leal 44(%esp), %esi
 	movl %ebx, %ecx
 	movl %esp, %edi
 	subl %ebx, %edi
 	andl $0xfffffff0, %edi	# Align stack
 	movl %esp, %ebx
-	cfi_def_cfa_register (3)
+	cfi_def_cfa_register (ebx)
 	movl %edi, %esp
 	shrl $2, %ecx
 	rep
 	movsl
 	movl (%edi), %esi
-	cfi_restore (6)
+	cfi_restore (esi)
 	movl 4(%edi), %edi
-	cfi_restore (7)
+	cfi_restore (edi)
 	/*
 	   %ebx+40  return address
 	   %ebx+36  PLT1
@@ -144,9 +144,9 @@ _dl_runtime_profile:
 	movl 20(%ebx), %eax
 	call *(%ebx)
 	movl %ebx, %esp
-	cfi_def_cfa_register (4)
+	cfi_def_cfa_register (esp)
 	movl 8(%esp), %ebx
-	cfi_restore (3)
+	cfi_restore (ebx)
 	/*
 	    +40     return address
 	    +36     PLT1
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_ceill.c b/sysdeps/ieee754/ldbl-128ibm/s_ceill.c
index 035e4f52ce..6252e9140b 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_ceill.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_ceill.c
@@ -1,6 +1,6 @@
 /* Ceil (round to +inf) long double floating-point values.
    IBM extended format long double version.
-   Copyright (C) 2006 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007 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
@@ -19,7 +19,6 @@
    02111-1307 USA.  */
 
 #include <math.h>
-#include <fenv_libc.h>
 #include <math_ldbl_opt.h>
 #include <float.h>
 #include <ieee754.h>
@@ -44,11 +43,9 @@ __ceill (x)
 					     __builtin_inf ()), 1))
     {
       double orig_xh;
-      int save_round = fegetround ();
 
       /* Long double arithmetic, including the canonicalisation below,
 	 only works in round-to-nearest mode.  */
-      fesetround (FE_TONEAREST);
 
       /* Convert the high double to integer.  */
       orig_xh = xh;
@@ -81,8 +78,6 @@ __ceill (x)
       /* Ensure we return -0 rather than +0 when appropriate.  */
       if (orig_xh < 0.0)
 	xh = -__builtin_fabs (xh);
-
-      fesetround (save_round);
     }
 
   return ldbl_pack (xh, xl);
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_copysignl.c b/sysdeps/ieee754/ldbl-128ibm/s_copysignl.c
index 7e7b44168d..1a198c16e8 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_copysignl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_copysignl.c
@@ -25,6 +25,7 @@ static char rcsid[] = "$NetBSD: $";
 
 #include "math.h"
 #include "math_private.h"
+#include <math_ldbl_opt.h>
 
 #ifdef __STDC__
 	long double __copysignl(long double x, long double y)
@@ -33,13 +34,13 @@ static char rcsid[] = "$NetBSD: $";
 	long double x,y;
 #endif
 {
-  if (y < 0.0)
-    {
-      if (x >= 0.0)
-	x = -x;
-    }
-  else if (x < 0.0)
+  if (signbit (x) != signbit (y))
     x = -x;
   return x;
 }
-weak_alias (__copysignl, copysignl)
+
+#ifdef IS_IN_libm
+long_double_symbol (libm, __copysignl, copysignl);
+#else
+long_double_symbol (libc, __copysignl, copysignl);
+#endif
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c b/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c
index 62663125ee..89eb205101 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c
@@ -37,7 +37,7 @@ static char rcsid[] = "$NetBSD: $";
 	GET_LDOUBLE_WORDS64(hx,lx,x);
 	lx = lx ^ ( hx & 0x8000000000000000LL );
 	hx = hx & 0x7fffffffffffffffLL;
-	SET_LDOUBLE_WORDS64(hx,lx,x);
-        return x;
+	SET_LDOUBLE_WORDS64(x,hx,lx);
+	return x;
 }
 long_double_symbol (libm, __fabsl, fabsl);
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_floorl.c b/sysdeps/ieee754/ldbl-128ibm/s_floorl.c
index 4c4ae9b035..eff7572405 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_floorl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_floorl.c
@@ -1,6 +1,6 @@
 /* Round to int long double floating-point values.
    IBM extended format long double version.
-   Copyright (C) 2006 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007 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
@@ -19,7 +19,6 @@
    02111-1307 USA.  */
 
 #include <math.h>
-#include <fenv_libc.h>
 #include <math_ldbl_opt.h>
 #include <float.h>
 #include <ieee754.h>
@@ -43,11 +42,8 @@ __floorl (x)
 			&& __builtin_isless (__builtin_fabs (xh),
 					     __builtin_inf ()), 1))
     {
-      int save_round = fegetround ();
-
       /* Long double arithmetic, including the canonicalisation below,
 	 only works in round-to-nearest mode.  */
-      fesetround (FE_TONEAREST);
 
       /* Convert the high double to integer.  */
       hi = ldbl_nearbyint (xh);
@@ -75,8 +71,6 @@ __floorl (x)
       xh = hi;
       xl = lo;
       ldbl_canonicalize (&xh, &xl);
-
-      fesetround (save_round);
     }
 
   return ldbl_pack (xh, xl);
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_roundl.c b/sysdeps/ieee754/ldbl-128ibm/s_roundl.c
index 0880e6ee22..d633bfa4c8 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_roundl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_roundl.c
@@ -1,6 +1,6 @@
 /* Round to int long double floating-point values.
    IBM extended format long double version.
-   Copyright (C) 2006 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007 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
@@ -22,7 +22,6 @@
    when it's coded in C.  */
 
 #include <math.h>
-#include <fenv_libc.h>
 #include <math_ldbl_opt.h>
 #include <float.h>
 #include <ieee754.h>
@@ -47,11 +46,9 @@ __roundl (x)
 					     __builtin_inf ()), 1))
     {
       double orig_xh;
-      int save_round = fegetround ();
 
       /* Long double arithmetic, including the canonicalisation below,
 	 only works in round-to-nearest mode.  */
-      fesetround (FE_TONEAREST);
 
       /* Convert the high double to integer.  */
       orig_xh = xh;
@@ -88,8 +85,6 @@ __roundl (x)
       xh = hi;
       xl = lo;
       ldbl_canonicalize (&xh, &xl);
-
-      fesetround (save_round);
     }
 
   return ldbl_pack (xh, xl);
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_truncl.c b/sysdeps/ieee754/ldbl-128ibm/s_truncl.c
index d7bc47ee0d..ceace0d43e 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_truncl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_truncl.c
@@ -1,6 +1,6 @@
 /* Truncate (toward zero) long double floating-point values.
    IBM extended format long double version.
-   Copyright (C) 2006 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007 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
@@ -22,7 +22,6 @@
    when it's coded in C.  */
 
 #include <math.h>
-#include <fenv_libc.h>
 #include <math_ldbl_opt.h>
 #include <float.h>
 #include <ieee754.h>
@@ -47,11 +46,9 @@ __truncl (x)
 					     __builtin_inf ()), 1))
     {
       double orig_xh;
-      int save_round = fegetround ();
 
       /* Long double arithmetic, including the canonicalisation below,
 	 only works in round-to-nearest mode.  */
-      fesetround (FE_TONEAREST);
 
       /* Convert the high double to integer.  */
       orig_xh = xh;
@@ -92,8 +89,6 @@ __truncl (x)
       /* Ensure we return -0 rather than +0 when appropriate.  */
       if (orig_xh < 0.0)
 	xh = -__builtin_fabs (xh);
-
-      fesetround (save_round);
     }
 
   return ldbl_pack (xh, xl);
diff --git a/sysdeps/unix/sysv/linux/getdents.c b/sysdeps/unix/sysv/linux/getdents.c
index 836cbf3922..b33d1789ad 100644
--- a/sysdeps/unix/sysv/linux/getdents.c
+++ b/sysdeps/unix/sysv/linux/getdents.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1993, 1995-2003, 2004, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1995-2003, 2004, 2006, 2007
+   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
@@ -50,8 +51,6 @@ extern int __have_no_getdents64 attribute_hidden;
 # define __have_no_getdents64 0
 #endif
 
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-
 /* For Linux we need a special version of this file since the
    definition of `struct dirent' is not the same for the kernel and
    the libc.  There is one additional field which might be introduced
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index 5286676fc1..89d5b12043 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992,1993,1995-2000,2002-2005,2006
+/* Copyright (C) 1992,1993,1995-2000,2002-2006,2007
    	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995.
@@ -566,15 +566,23 @@ asm (".L__X'%ebx = 1\n\t"
    is too complicated here since we have no PC-relative addressing mode.  */
 #else
 # ifdef __ASSEMBLER__
-#  define PTR_MANGLE(reg)	xorl %gs:POINTER_GUARD, reg
-#  define PTR_DEMANGLE(reg)	PTR_MANGLE (reg)
+#  define PTR_MANGLE(reg)	xorl %gs:POINTER_GUARD, reg;		      \
+				roll $9, reg
+#  define PTR_DEMANGLE(reg)	rorl $9, reg;				      \
+				xorl %gs:POINTER_GUARD, reg
 # else
-#  define PTR_MANGLE(var)	asm ("xorl %%gs:%c2, %0"		      \
+#  define PTR_MANGLE(var)	asm ("xorl %%gs:%c2, %0\n"		      \
+				     "roll $9, %0"			      \
+				     : "=r" (var)			      \
+				     : "0" (var),			      \
+				       "i" (offsetof (tcbhead_t,	      \
+						      pointer_guard)))
+#  define PTR_DEMANGLE(var)	asm ("rorl $9, %0\n"			      \
+				     "xorl %%gs:%c2, %0"		      \
 				     : "=r" (var)			      \
 				     : "0" (var),			      \
 				       "i" (offsetof (tcbhead_t,	      \
 						      pointer_guard)))
-#  define PTR_DEMANGLE(var)	PTR_MANGLE (var)
 # endif
 #endif
 
diff --git a/sysdeps/unix/sysv/linux/sys/personality.h b/sysdeps/unix/sysv/linux/sys/personality.h
index 5d14a9bc80..ff7c61aa52 100644
--- a/sysdeps/unix/sysv/linux/sys/personality.h
+++ b/sysdeps/unix/sysv/linux/sys/personality.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2007 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
@@ -16,7 +16,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-/* Taken verbatim from Linux 2.4 (include/linux/personality.h).  */
+/* Taken verbatim from Linux 2.6 (include/linux/personality.h).  */
 
 #ifndef _SYS_PERSONALITY_H
 #define _SYS_PERSONALITY_H 1
@@ -27,11 +27,13 @@
    These occupy the top three bytes.  */
 enum
   {
+    ADDR_NO_RANDOMIZE = 0x0040000,
     MMAP_PAGE_ZERO = 0x0100000,
     ADDR_LIMIT_32BIT = 0x0800000,
     SHORT_INODE = 0x1000000,
     WHOLE_SECONDS = 0x2000000,
     STICKY_TIMEOUTS = 0x4000000,
+    ADDR_LIMIT_3GB = 	0x8000000
   };
 
 /* Personality types.
@@ -52,14 +54,15 @@ enum
     PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
     PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
     PER_LINUX32 = 0x0008,
+    PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
     PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,	/* IRIX5 32-bit */
     PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,	/* IRIX6 new 32-bit */
     PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,	/* IRIX6 64-bit */
     PER_RISCOS = 0x000c,
     PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
     PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
-    PER_HPUX = 0x000f,
-    PER_OSF4 = 0x0010,
+    PER_OSF4 = 0x000f,
+    PER_HPUX = 0x0010,
     PER_MASK = 0x00ff,
   };
 
diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
index 5dfffca455..3a0a632aab 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2005, 2007 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
@@ -317,24 +317,37 @@
 /* We cannot use the thread descriptor because in ld.so we use setjmp
    earlier than the descriptor is initialized.  */
 # ifdef __ASSEMBLER__
-#  define PTR_MANGLE(reg)	xorq __pointer_chk_guard_local(%rip), reg
-#  define PTR_DEMANGLE(reg)	PTR_MANGLE (reg)
+#  define PTR_MANGLE(reg)	xorq __pointer_chk_guard_local(%rip), reg;    \
+				rolq $17, reg
+#  define PTR_DEMANGLE(reg)	rorq $17, reg;				      \
+				xorq __pointer_chk_guard_local(%rip), reg
 # else
-#  define PTR_MANGLE(reg)	asm ("xorq __pointer_chk_guard_local(%%rip), %0"\
+#  define PTR_MANGLE(reg)	asm ("xorq __pointer_chk_guard_local(%%rip), %0\n" \
+				     "rolq $17, %0"			      \
+				     : "=r" (reg) : "0" (reg))
+#  define PTR_DEMANGLE(reg)	asm ("rorq $17, %0\n"			      \
+				     "xorq __pointer_chk_guard_local(%%rip), %0" \
 				     : "=r" (reg) : "0" (reg))
-#  define PTR_DEMANGLE(reg)	PTR_MANGLE (reg)
 # endif
 #else
 # ifdef __ASSEMBLER__
-#  define PTR_MANGLE(reg)	xorq %fs:POINTER_GUARD, reg
-#  define PTR_DEMANGLE(reg)	PTR_MANGLE (reg)
+#  define PTR_MANGLE(reg)	xorq %fs:POINTER_GUARD, reg;		      \
+				rolq $17, reg
+#  define PTR_DEMANGLE(reg)	rorq $17, reg;				      \
+				xorq %fs:POINTER_GUARD, reg
 # else
-#  define PTR_MANGLE(var)	asm ("xorq %%fs:%c2, %0"		      \
+#  define PTR_MANGLE(var)	asm ("xorq %%fs:%c2, %0\n"		      \
+				     "rolq $17, %0"			      \
+				     : "=r" (var)			      \
+				     : "0" (var),			      \
+				       "i" (offsetof (tcbhead_t,	      \
+						      pointer_guard)))
+#  define PTR_DEMANGLE(var)	asm ("rorq $17, %0\n"			      \
+				     "xorq %%fs:%c2, %0"		      \
 				     : "=r" (var)			      \
 				     : "0" (var),			      \
 				       "i" (offsetof (tcbhead_t,	      \
 						      pointer_guard)))
-#  define PTR_DEMANGLE(var)	PTR_MANGLE (var)
 # endif
 #endif
 
diff --git a/sysdeps/x86_64/bits/byteswap.h b/sysdeps/x86_64/bits/byteswap.h
index e1c861c75f..7514a9f4db 100644
--- a/sysdeps/x86_64/bits/byteswap.h
+++ b/sysdeps/x86_64/bits/byteswap.h
@@ -1,5 +1,6 @@
 /* Macros to swap the order of bytes in integer values.
-   Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2000, 2002, 2003, 2007
+   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
@@ -59,7 +60,8 @@
 # if __WORDSIZE == 64 || (defined __i486__ || defined __pentium__	      \
 			  || defined __pentiumpro__ || defined __pentium4__   \
 			  || defined __k8__ || defined __athlon__	      \
-			  || defined __k6__)
+			  || defined __k6__ || defined __nocona__	      \
+			  || defined __core2__ || defined __geode__)
 /* To swap the bytes in a word the i486 processors and up provide the
    `bswap' opcode.  On i386 we have to use three instructions.  */
 #  define __bswap_32(x) \
diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h
index f54abfaa96..3c5a8cb810 100644
--- a/wcsmbs/wchar.h
+++ b/wcsmbs/wchar.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995-2004,2005,2006 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2004,2005,2006,2007 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
@@ -414,7 +414,7 @@ extern unsigned long int wcstoul (__const wchar_t *__restrict __nptr,
      __THROW;
 
 #if defined __USE_ISOC99 || (defined __GNUC__ && defined __USE_GNU)
-/* Convert initial portion of wide string NPTR to `long int'
+/* Convert initial portion of wide string NPTR to `long long int'
    representation.  */
 __extension__
 extern long long int wcstoll (__const wchar_t *__restrict __nptr,
@@ -431,7 +431,7 @@ extern unsigned long long int wcstoull (__const wchar_t *__restrict __nptr,
 __END_NAMESPACE_C99
 
 #if defined __GNUC__ && defined __USE_GNU
-/* Convert initial portion of wide string NPTR to `long int'
+/* Convert initial portion of wide string NPTR to `long long int'
    representation.  */
 __extension__
 extern long long int wcstoq (__const wchar_t *__restrict __nptr,